summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2014-09-26 06:12:12 -0700
committerKaz Kylheku <kaz@kylheku.com>2014-09-26 06:12:12 -0700
commit99131c676125d2c78f41e0ef42ad3d8433a7fac5 (patch)
tree7542b5772ad2689947c57efcfbe27c8bb6e1e3aa
parent843db24e847619b35baeeb7cf88991ad48427bb6 (diff)
downloadtxr-99131c676125d2c78f41e0ef42ad3d8433a7fac5.tar.gz
txr-99131c676125d2c78f41e0ef42ad3d8433a7fac5.tar.bz2
txr-99131c676125d2c78f41e0ef42ad3d8433a7fac5.zip
* txr.1: Substantially revised with rich troff markup,
and restructured in some places. * genman.txr: No longer generate the whole document in monospaced font. Add hyperlinks.
-rw-r--r--ChangeLog8
-rw-r--r--genman.txr42
-rw-r--r--txr.128947
3 files changed, 18968 insertions, 10029 deletions
diff --git a/ChangeLog b/ChangeLog
index 058fa6d0..83d9da18 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2014-09-26 Kaz Kylheku <kaz@kylheku.com>
+
+ * txr.1: Substantially revised with rich troff markup,
+ and restructured in some places.
+
+ * genman.txr: No longer generate the whole document in
+ monospaced font. Add hyperlinks.
+
2014-09-25 Kaz Kylheku <kaz@kylheku.com>
* lib.c (do_and, do_or): Fix broken andf and orf,
diff --git a/genman.txr b/genman.txr
index d7fa1bf1..2f225743 100644
--- a/genman.txr
+++ b/genman.txr
@@ -2,10 +2,13 @@
@# and is now part of manutils.
@# See here: http://primates.ximian.com/~flucifredi/man/
@# It does not work with that other man2html written in Perl.
-@(deffilter month_name
+@(deffilter month-name
("01" "Jan") ("02" "Feb") ("03" "Mar") ("04" "Apr")
("05" "May") ("06" "Jun") ("07" "Jul") ("08" "Aug")
("09" "Sep") ("10" "Oct") ("11" "Nov") ("12" "Dec"))
+@(bind txrhash @(hash :equal-based))
+@(bind txlhash @(hash :equal-based))
+@(bind tgthash txrhash)
Content-type: text/html
@(skip 15)
<H1>TXR</H1>
@@ -15,29 +18,58 @@ Content-type: text/html
@(until)
txr - text processing language @(skip)
@(end)
+@(bind lookup @[orf txrhash txlhash])
@(all)
txr - text processing language @VERSION
@ (and)
-@ (collect)
+@ (collect :vars (BODY LOOKUP))
+@ (some)
@BODY
+@ (and)
+<H2>13 TXR LISP</H2>
+@ (set lookup @[orf txlhash txrhash])
+@ (end)
+@ (bind LOOKUP lookup)
@ (until)
<HR>
<A NAME="index">&nbsp;</A><H2>Index</H2>
@ (end)
@(end)
<HR>
-@(collect)
+@(collect :vars (TOC))
+@ (some)
@TOC
+@ (and)
+<DT><A HREF="@nil">@nil TXR LISP</A><DD>
+@ (set tgthash txlhash)
+@ (and)
+<DT><A HREF="@tag">@(coll :vars (sym))<TT>@sym</TT>@(end)
+@ (do (mapdo (do unless [tgthash @1] (set [tgthash @1] tag))
+ sym))
+@ (end)
@(until)
This document was created by
@(end)
+@(set BODY @(mapcar (do if (search-regex @1 #/<H[1-9]>/)
+ @1
+ (regsub #/<TT>.%<\/TT>/
+ (do let ((tok [@1 4 -5]) tag)
+ (if (match-str tok "@(")
+ (let ((sym [tok 2 -1]))
+ (set tag [txrhash sym]))
+ (set tag [@@2 tok]))
+ (if tag
+ `<A HREF="@tag">@1</A>`
+ @1))
+ @1))
+ BODY
+ LOOKUP))
@(output)
<HTML>
-<FONT FACE="courier">
<HEAD><TITLE>Manpage for TXR @VERSION</TITLE>
</HEAD><BODY>
<H2>Manpage for <A HREF="#lbAB">TXR </a>@VERSION</H2>
-<H2>@{MONTH :filter month_name} @DAY, @YEAR</H2>
+<H2>@{MONTH :filter month-name} @DAY, @YEAR</H2>
@(repeat)
@TOC
@(end)
diff --git a/txr.1 b/txr.1
index 16a91684..5998f6b4 100644
--- a/txr.1
+++ b/txr.1
@@ -1,3 +1,4 @@
+.\" t '\" vim:set syntax=groff:
.\"Copyright (C) 2009-2014 Kaz Kylheku <kaz@kylheku.com>.
.\"All rights reserved.
.\"
@@ -20,14 +21,326 @@
.\"THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
.\"IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
.\"WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
-
-.TH "TXR" 1 2014-08-14 "Utility Commands" "TXR Text Processing Language" "Kaz Kylheku"
-.SH NAME
+.\"
+.\" Useful groff definitions.
+.\"
+.\" Some constants that depend on troff/nroff mode:
+.ie n \{\
+.ds vspc 1
+.\}
+.el \{\
+.ds vspc 0.5
+.\}
+.\" Mount numeric fonts when not running under man2html
+.if !\n(M2 \{\
+. fp 4 CR
+. fp 5 CI
+.\}
+.\" Base font
+.nr fsav 1
+.\" start of code block: switch to monospace font
+.de cblk
+. ft 4
+..
+.\" end of code block: restore font
+.de cble
+. ft 1
+..
+.\" typeset arguments in monospace
+.\" .code x y z -> \f[CR]x y z\f[]
+.de code
+\f[4]\\$*\f[]
+..
+.\" like .code typesets meta-syntax
+.\" which is done in angle brackets in nroff or oblique
+.\" courier in PDF/HTML.
+.de meta
+. ie n \{\
+<\\$*>
+. \}
+. el \{\
+\f[5]\\$*\f[]
+. \}
+..
+.\" like .meta but tack on second agument with no space.
+.de metn
+. ie n \{\
+<\\$1>\\$2
+. \}
+. el \{\
+\f[5]\\$1\f[]\\$2
+. \}
+..
+.\" like .code but wraps in quotes
+.\" .str x y z -> \f[CR]"x y z"\f[].
+.de str
+\f[4]"\\$*"\f[]
+..
+.\" wrap first argument in quotes, tack no second one with no space
+.\" .strn x y -> \f[CR]"x"\f[]y.
+.de strn
+\f[4]"\\$1"\f[]\\$2
+..
+.\" like .IP but use monospace too
+.de coIP
+. IP "\\f[4]\\$*\\f[]"
+..
+.\" Directive heading
+.de dir
+. SS* The \f[4]\\$1\f[] directive
+..
+.\" Multiple directive heading
+.de dirs
+. while (\\n[.$]>2) \{\
+. as s \f[4]\\$1\f[],
+. shift
+. \}
+. if (\\n[.$]>1) \{\
+. as s \f[4]\\$1\f[]
+. shift
+. \}
+. if (\\n[.$]>0) \{\
+. as s and \f[4]\\$1\f[]
+. \}
+. SS* The \\*s directives
+..
+.\" heading with code in position 1
+.de c1SS
+. ds s \\f[4]\\$1\\f[]
+. shift
+. as s " \\$*
+. SS* \\*s
+..
+.\" utility macro for gathering material into "s" string.
+.\" a pair of arguments "@ arg" becomes arg set in code
+.\" a pair of arguments "@, arg" becomes "arg," where
+.\" arg is set in code, followed by comma not in code.
+.de gets
+. ds s "
+. while (\\n[.$]>0) \{\
+. ie "\\$1"@" \{\
+. shift
+. as s \f[4]\\$1\f[]
+. shift
+. \}
+. el \{\
+. ie "\\$1"@," \{\
+. shift
+. as s \f[4]\\$1\f[],
+. shift
+. \}
+. el \{\
+. as s \\$1
+. shift
+. \}
+. \}
+. \}
+..
+.\" a macro for gathering material into "s"
+.\" a pair of arguments "< arg" is typeset like
+.\" .meta arg. "<< arg arg" is like .metn arg arg.
+.ie n \{\
+. de getm
+. ds s "
+. while (\\n[.$]>0) \{\
+. ie "\\$1"<" \{\
+. shift
+. as s <\\$1>
+. shift
+. \}
+. el \{\
+. ie "\\$1"<<" \{\
+. shift
+. as s <\\$1>\\$2
+. shift
+. shift
+. \}
+. el \{\
+. ie "\\$1">>" \{\
+. shift
+. as s \\$1<\\$2>
+. shift
+. shift
+. \}
+. el \{\
+. ie "\\$1"<>" \{\
+. shift
+. as s \\$1<\\$2>\\$3
+. shift
+. shift
+. shift
+. \}
+. el \{\
+. as s \\$1
+. shift
+. \}
+. \}
+. \}
+. \}
+. \}
+. .
+.\}
+.el \{\
+. de getm
+. ds s "
+. while (\\n[.$]>0) \{\
+. ie "\\$1"<" \{\
+. shift
+. as s \\f5\\$1\\f4
+. shift
+. \}
+. el \{\
+. ie "\\$1"<<" \{\
+. shift
+. as s \\f5\\$1\\f4\\$2
+. shift
+. shift
+. \}
+. el \{\
+. ie "\\$1">>" \{\
+. shift
+. as s \\$1\\f5\\$2\\f4
+. shift
+. shift
+. \}
+. el \{\
+. ie "\\$1"<>" \{\
+. shift
+. as s \\$1\\f5\\$2\f4\\$3
+. shift
+. shift
+. shift
+. \}
+. el \{\
+. as s \\$1
+. shift
+. \}
+. \}
+. \}
+. \}
+. \}
+. .
+.\}
+.\" typeset all arguments by the last one in monospace, followed
+.\" by the last one in previous font with no space
+.\" .codn x y ... z -> \f[CR]x y ...\f[]z
+.de codn
+. ds s "
+. while (\\n[.$]>2) \{\
+. as s \\$1
+. shift
+. \}
+\f[4]\\*s\\$1\f[]\\$2
+..
+.\" .cod1 a b c -> abc where a is typeset as code
+.de cod1
+\\$1\f[4]\\$2\f[]\$3
+..
+.\" .cod2 a b -> ab where b is typeset as code
+.de cod2
+\\$1\f[4]\\$2\f[]
+..
+.\" .cod3 a b c -> abc where a and c are typeset as code
+.de cod3
+\f[4]\\$1\f[]\\$2\f[4]\\$3\f[]
+..
+.\" Syntax section markup
+.de synb
+. TP* Syntax:
+. cblk
+..
+.de syne
+. cble
+..
+.\" Used for meta-variables in syntax blocks
+.de mets
+. nr fsav \\n[.f]
+. getm \\$*
+ \\*s
+. ft \\n[fsav]
+..
+.\" Used for meta-variables in inline blocks
+.de meti
+. nr fsav \\n[.f]
+. getm \\$*
+\\*s
+. ft \\n[fsav]
+..
+.\" Used for meta-variables in .coIP
+.de meIP
+. nr fsav \\n[.f]
+. getm \\$*
+.coIP \\*s
+. ft \\n[fsav]
+..
+.\" Description section
+.de desc
+. TP* Description:
+..
+.\" Section counters: heading, section, paragraph.
+.nr shco 0 1
+.nr ssco 0 1
+.nr spco 0 1
+.\" wrapper for .SH
+.de SH*
+. SH \\n+[shco] \\$*
+. rs
+. nr ssco 0
+. nr spco 0
+. sp \*[vspc]
+. ns
+..
+.\" wrapper for .SS
+.de SS*
+. SS \\n[shco].\\n+[ssco] \\$*
+. rs
+. nr spco 0
+. sp \*[vspc]
+. ns
+..
+.\" wrapper for .TP
+.de TP*
+. ds s \\$1
+. shift
+. TP \\$*
+\\*s
+. sp \*[vspc]
+. ns
+..
+.\" numbered paragraph
+.de NP*
+. ie \n(M2 \{\
+. M2SS 2 H4 "\\n[shco].\\n[ssco].\\n+[spco] \\$*"
+. \}
+. el \{\
+. TP* "\f[B]\\n[shco].\\n[ssco].\\n+[spco] \\$*\f[]"
+. \}
+. PP
+..
+.\" process arguments using .gets so that some material
+.\" is typeset as code. Then pass to .SS* section macro.
+.de coSS
+. gets \\$*
+. SS* \\*s
+..
+.\" like coSS but targetting NP*
+.de coNP
+. gets \\$*
+. NP* \\*s
+..
+.\" like coSS but use monospace IP
+.de ccIP
+. gets \\$*
+. IP "\\*s"
+..
+.\" Start of man page:
+.TH "TXR" 1 2014-08-14 "Utility Commands" "TXR Data Processing Language" "Kaz Kylheku"
+.SH* NAME
txr \- text processing language (version 97)
-.SH SYNOPSIS
-.B txr [ options ] query-file { data-file }*
+.SH* SYNOPSIS
+.code txr [ options ] query-file { data-file }*
.sp
-.SH DESCRIPTION
+.SH* DESCRIPTION
.B TXR
is a language oriented toward processing text from files or streams, using
multiple programming paradigms.
@@ -38,7 +351,9 @@ script is called a query, and it specifies a pattern which matches (a prefix
of) an entire file, or multiple files. Patterns can consists of large
chunks of multi-line free-form text, which is matched literally
against material in the input sources. Free variables occurring in the pattern
-(denoted by the @ symbol) are bound to the pieces of text occurring in the
+(denoted by the
+.code @
+symbol) are bound to the pieces of text occurring in the
corresponding positions. If the overall match is successful, then
.B TXR
can do one of two things: it can report the list of variables which were bound,
@@ -65,15 +380,23 @@ functional and imperative programming, and provides data types such as symbols,
strings, vectors, hash tables with weak reference support, lazy lists, and
arbitrary-precision (bignum integers).
-.SH ARGUMENTS AND OPTIONS
+.SH* ARGUMENTS AND OPTIONS
Options which don't take an argument may be combined together.
-The -v and -q options are mutually exclusive. Of these two, the one which
+The
+.code -v
+and
+.code -q
+options are mutually exclusive. Of these two, the one which
occurs in the rightmost position in the argument list dominates.
-The -c and -f options are also mutually exclusive; if both are specified,
+The
+.code -c
+and
+.code -f
+options are also mutually exclusive; if both are specified,
it is a fatal error.
-.IP -Dvar=value
+.coIP -Dvar=value
Bind the variable
.IR var
to the value
@@ -82,58 +405,68 @@ prior to processing the query. The name is in scope over the entire
query, so that all occurrence of the variable are substituted and
match the equivalent text. If the value contains commas, these
are interpreted as separators, which give rise to a list value.
-For instance -Da,b,c creates a list of the strings "a", "b" and "c".
+For instance
+.code -Da,b,c
+creates a list of the strings
+.strn "a" ,
+.str "b"
+and
+.strn "c" .
(See Collect Directive bellow). List variables provide a multiple
match. That is to say, if a list variable occurs in a query, a successful
match occurs if any of its values matches the text. If more than one
value matches the text, the first one is taken.
-.IP -Dvar
+.coIP -Dvar
Binds the variable
.IR var
to an empty string value prior to processing the query.
-.IP -q
+.coIP -q
Quiet operation during matching. Certain error messages are not reported on the
standard error device (but the if the situations occur, they still fail the
query). This option does not suppress error generation during the parsing
of the query, only during its execution.
-.IP -d
-.IP --debugger
+.coIP -d
+.coIP --debugger
Invoke the interactive txr debugger. See the DEBUGGER section.
-.IP -v
+.coIP -v
Verbose operation. Detailed logging is enabled.
-.IP -b
+.coIP -b
This is a deprecated option, which is silently ignored. In TXR versions
prior to 90, the printing of variable bindings (see -B option) was
implicit behavior which was automatically suppressed in certain situations.
The -b option suppressed it unconditionally.
-.IP -B
+.coIP -B
If the query is successful, print the variable bindings as a sequence
of assignments in shell syntax can be eval-ed by a POSIX shell.
If the query fails, print the word "false". Evaluation of this word
by the shell has the effect of producing an unsuccessful termination
status from the eval command.
-.IP "-l or --lisp-bindings"
+.coIP "-l or --lisp-bindings"
This option implies -B. Print the variable bindings in Lisp syntax instead of
shell syntax.
-.IP "-a num"
+.coIP "-a num"
This option implies -B. The decimal integer argument specifies the maximum
number of array dimensions to use for list-valued variable bindings.
The default is 1. Additional dimensions are expressed using numeric suffixes
in the generated variable names.
For instance, consider the three-dimensional list arising out of a triply
-nested collect: ((("a" "b") ("c" "d")) (("e" "f") ("g" "h"))).
+nested collect:
+.cblk
+((("a" "b") ("c" "d")) (("e" "f") ("g" "h"))).
+.cble
Suppose this is bound to a variable V. With -a 1, this will be
reported as:
+.cblk
V_0_0[0]="a"
V_0_1[0]="b"
V_1_0[0]="c"
@@ -142,65 +475,100 @@ reported as:
V_0_1[1]="f"
V_1_0[1]="g"
V_1_1[1]="h"
+.cble
The leftmost bracketed index is the most major index. That is to say,
-the dimension order is: NAME_m_m+1_..._n[1][2]...[m-1].
+the dimension order is:
+.codn "NAME_m_m+1_..._n[1][2]...[m-1]" .
-.IP "-c query"
+.coIP "-c query"
Specifies the query in the form of a command line argument. If this option is
used, the query-file argument is omitted. The first non-option argument,
if there is one, now specifies the first input source rather than a query.
Unlike queries read from a file, (non-empty) queries specified as arguments
using -c do not have to properly end in a newline. Internally, TXR
-adds the missing newline before parsing the query. Thus -c "@a"
+adds the missing newline before parsing the query. Thus
+.code -c
+.str @a
is a valid query which matches a line.
Example:
- # read two lines "1" and "2" from standard input,
- # binding them to variables a and b. Standard
- # input is specified as - and the data
- # comes from shell "here document" redirection.
-
- txr -B -c "@a
- @b" - <<!
- 1
- 2
- !
-
- Output:
- a=1
- b=2
+Shell script which uses
+.B TXR
+to read two lines
+.str 1
+and
+.str 2
+from standard input,
+binding them to variables
+.code a
+and
+.codn b .
+Standard
+input is specified as
+.code -
+and the data
+comes from shell "here document" redirection:
+.RS
+.IP code:
+.cblk
+\ #!/bin/sh
+
+ txr -B -c "@a
+ @b" - <<!
+ 1
+ 2
+ !
+.cble
+
+.IP output:
+.cblk
+\ a=1
+ b=2
+.cble
+.PP
-The @; comment syntax can be used for better formatting:
+The
+.code @;
+comment syntax can be used for better formatting:
+.cblk
txr -B -c "@;
@a
@b"
+.cble
+.RE
-.IP "-f query-file"
+.coIP "-f query-file"
Specifies the file from which the query is to be read, instead of the
-query-file argument. This is useful in #! scripts. (See Hash Bang Support
-below).
+query-file argument. This is useful in
+.code #!
+("hash bang") scripts. (See Hash Bang Support below).
-.IP "-e expression"
+.coIP "-e expression"
Evaluates a TXR Lisp expression for its side effects, without printing
-its value. Can be specified more than once. The query-file argument becomes
-optional if -e is used at least once.
+its value. Can be specified more than once. The
+.code query-file
+argument becomes optional if
+.code -e
+is used at least once.
-.IP "-p expression"
+.coIP "-p expression"
Evaluates a TXR Lisp expression and prints its value. Can be specified more
-than once. The query-file argument becomes optional if -p is used at least
-once.
+than once. The query-file argument becomes optional if
+.code -p
+is used at least once.
-.IP "-C number"
-.IP "--compat=number"
+.coIP "-C number"
+.coIP "--compat=number"
Requests TXR to behave in a manner that is compatible with the specified
version of TXR. This makes a difference in situations when a release of
TXR breaks backward compatibility. If some version N+1 deliberately introduces
-a change which is backward incompatible, then -C N can be used to request
-the old behavior.
+a change which is backward incompatible, then
+.code -C N
+can be used to request the old behavior.
The requested value of N can be too low, in which case TXR
will complain and exit with an unsuccessful termination status. This indicates
@@ -212,48 +580,52 @@ If the option is specified more than once, the behavior is not specified.
For more information, see the COMPATIBILITY section.
-.IP "--gc-delta=number"
+.coIP "--gc-delta=number"
The argument to this option must be a decimal integer. It represents
a megabyte value, the "GC delta": one megabyte is 1048576 bytes. The "GC
delta" controls an aspect of the garbage collector behavior.
-See the gc-set-delta function for a description.
+See the
+.code gc-set-delta
+function for a description.
-.IP --help
+.coIP --help
Prints usage summary on standard output, and terminates successfully.
-.IP --license
+.coIP --license
Prints the software license. This depends on the software being
installed such that the LICENSE file is in the data directory.
Use of txr implies agreement with the liability disclaimer in the license.
-.IP --version
+.coIP --version
Prints program version standard output, and terminates successfully.
-.IP --args
+.coIP --args
The --args option provides a way to encode multiple arguments as a single
argument, which is useful on some systems which have limitations in
their implementation of the "hash bang" mechanism. See Hash Bang Support
below.
-.IP --
-Signifies the end of the option list. This option does not combine with others,
-so for instance -b- does not mean -b --, but is an error.
+.coIP --
+Signifies the end of the option list.
-.IP -
+.coIP -
This argument is not interpreted as an option, but treated as a filename
argument. After the first such argument, no more options are recognized. Even
if another argument looks like an option, it is treated as a name.
This special argument - means "read from standard input" instead of a file.
The query file, or any of the data files, may be specified using this option.
-If two or more files are specified as -, the behavior is system-dependent.
+If two or more files are specified as
+.codn - ,
+the behavior is system-dependent.
It may be possible to indicate EOF from the interactive terminal, and
then specify more input which is interpreted as the second file, and so forth.
.PP
After the options, the remaining arguments are files. The first file argument
specifies the query, and is mandatory. A file argument consisting of a single
-- means to read the standard input instead of opening a file. A file argument
+.code -
+means to read the standard input instead of opening a file. A file argument
which begins with an exclamation symbol means that the rest of the argument is
a shell command which is to be run as a coprocess, and its output read like a
file.
@@ -267,17 +639,24 @@ material from that file, and then the contents are read on demand, not all at
once.
If no files arguments are specified on the command line, it is up to the
-query to open a file, pipe or standard input via the @(next) directive
+query to open a file, pipe or standard input via the
+.code @(next)
+directive
prior to attempting to make a match. If a query attempts to match text,
but has run out of files to process, the match fails.
-.SH STATUS AND ERROR REPORTING
+.SH* STATUS AND ERROR REPORTING
.B TXR
sends errors and verbose logs to the standard error device. The following
paragraphs apply when
.B TXR
-is run without enabling verbose mode with -v, or the printing of variable
-bindings with -B or -a.
+is run without enabling verbose mode with
+.codn -v ,
+or the printing of variable
+bindings with
+.code -B
+or
+codn -a .
If the command line arguments are incorrect, or the query has a malformed
syntax,
@@ -292,57 +671,82 @@ If the query is well-formed, and matches, then
.B TXR
issues no diagnostics, and terminates with a successful status.
-In verbose mode (-v),
+In verbose mode (option
+.codn -v ),
.B TXR
issues diagnostics on the standard error device even in situations which are
not erroneous.
-In bindings-printing mode (-B or -a),
+In bindings-printing mode (options
+.code -B
+or
+.codn -a) ,
.B TXR
-prints the word "false" if the query fails, and exits with a failed
+prints the word
+.code false
+if the query fails, and exits with a failed
termination status. If the query succeeds, the variable bindings, if any,
are output on standard output.
-.SH BASIC QUERY SYNTAX AND SEMANTICS
-
-.SS Comments
-
-A query may contain comments which are delimited by the sequence @; and
-extend to the end of the line. No whitespace can occur between the @ and ;.
+.SH* BASIC QUERY SYNTAX AND SEMANTICS
+.SS* Comments
+A query may contain comments which are delimited by the sequence
+.code @;
+and extend to the end of the line. No whitespace can occur between the
+.code @
+and
+.codn ; .
A comment which begins on a line swallows that entire line, as well as the
newline which terminates it. In essence, the entire comment disappears.
If the comment follows some material in a line, then it does not consume
the newline. Thus, the following two queries are equivalent:
+.IP 1.
+.cblk
+\ @a@; comment: match whole line against variable @a
+ @; this comment disappears entirely
+ @b
+.cble
- 1. @a@; comment: match whole line against variable @a
- @; this comment disappears entirely
- @b
+.IP 2.
+.cblk
+\ @a
+ @b
+.cble
- 2. @a
- @b
+.PP
-The comment after the @a does not consume the newline, but the
+The comment after the
+.code @a
+does not consume the newline, but the
comment which follows does. Without this intuitive behavior,
line comment would give rise to empty lines that must match empty
lines in the data, leading to spurious mismatches.
-Instead of the ; character, the # character can be used. This is
-an obsolescent feature.
-
-
-.SS Hash Bang Support
+Instead of the
+.code ;
+character, the
+.code #
+character can be used. This is an obsolescent feature.
+.SS* Hash Bang Support
TXR has several features which support use of the "hash bang" convention
for creating apparently stand-alone executable programs.
-If the first line of a query begins with the characters #!,
+If the first line of a query begins with the characters
+.codn #! ,
that entire line is deleted from the query. This allows
for TXR queries to be turned into standalone executable programs in the POSIX
environment.
-Shell example: create a simple executable program called "twoline.txr" and
-run it. This assumes txr is installed in /usr/bin.
+Shell example: create a simple executable program called
+.str "twoline.txr"
+and
+run it. This assumes
+.code txr
+is installed in
+.codn /usr/bin .
+.cblk
$ cat > hello.txr
#!/usr/bin/txr
@(bind a "Hey")
@@ -352,76 +756,115 @@ run it. This assumes txr is installed in /usr/bin.
$ chmod a+x hello.txr
$ ./hello.txr
Hello, world!
+.cble
When this plain hash bang line is used, txr receives the name of the script
as an argument. Therefore, it is not possible to pass additional options
to txr. For instance, if the above script is invoked like this
+.cblk
$ ./hello.txr -B
+.cble
the -B option isn't processed by txr, but treated as an additional argument,
-just as if "txr <scriptname> -B" had been executed directly.
+just as if
+.cblk
+.meti txr < scriptname -B
+.cble
+had been executed directly.
This behavior is useful if the script author wants not to expose the txr
options to the user of the script.
-However, the hash bang line can use the -f option:
+However, the hash bang line can use the
+.code -f
+option:
+.cblk
#!/usr/bin/txr -f
+.cble
-Now, the name of the script is passed as an argument to the -f option,
-and TXR will look for more options after that, so that the resulting
+Now, the name of the script is passed as an argument to the
+.code -f
+option, and TXR will look for more options after that, so that the resulting
program appears to accept TXR options. Now we can run
+.cblk
$ ./hello.txr -B
Hello, world!
a="Hey"
+.cble
-The -B option is honored.
+The
+.code -B
+option is honored.
On some operating systems, it is not possible to pass more than one
argument through the hash bang mechanism. That is to say, this will
not work.
+.cblk
#!/usr/bin/txr -B -f
-
-To support systems like this, TXR supports special argument called
---args. With --args, it is possible to encode multiple arguments
-into one argument. The --args option must be followed by a separator
+.cble
+
+To support systems like this, TXR supports the special argument
+.codn --args .
+With
+.codn --args ,
+it is possible to encode multiple arguments
+into one argument. The
+.code --args
+option must be followed by a separator
character, chosen by the programmer. The characters after that are
-split into multiple arguments on the separator character. The --args
+split into multiple arguments on the separator character. The
+.code --args
option is then removed from the argument list and replaced with these
arguments, which are processed in its place.
Example:
+.cblk
#!/usr/bin/txr --args:-B:-f
+.cble
The above has the same behavior as
+.cblk
#!/usr/bin/txr -B -f
+.cble
on a system which supports multiple arguments in hash bang.
The separator character is the colon, and so the remainder
-of that argument, -B:-f, is split into the two arguments -B -f.
-
-.SS Whitespace
+of that argument,
+.codn -B:-f ,
+is split into the two arguments
+.codn "-B -f" .
+.SS* Whitespace
Outside of directives, whitespace is significant in TXR queries, and represents
a pattern match for whitespace in the input. An extent of text consisting of
an undivided mixture of tabs and spaces is a whitespace token.
Whitespace tokens match a precisely identical piece of whitespace in the input,
with one exception: a whitespace token consisting of precisely one space has a
-special meaning. It is equivalent to the regular expression @/[ ]+/: match
-an extent of one or more spaces (but not tabs!)
-
-Thus, the query line "a b" (one space) matches texts like "a b", "a b", et
-cetera (arbitrary number of tabs and spaces between a and b). However "a b"
-(two spaces) matches only "a b" (two spaces).
-
-For matching a single space, the syntax @\e can be used (backslash-escaped
-space).
+special meaning. It is equivalent to the regular expression
+.codn "@/[ ]+/" :
+match an extent of one or more spaces (but not tabs!). Multiple consecutive
+spaces do not have this meaning.
+
+Thus, the query line
+.str "a b"
+(one space between
+.code a
+and
+codn b )
+matches
+.str "a b"
+with any number of spaces between the two letters.
+
+For matching a single space, the syntax
+.code "@\e "
+can be used (backslash-escaped space).
It is more often necessary to match multiple spaces, than to exactly
match one space, so this rule simplifies many queries and adds inconvenience
@@ -430,10 +873,10 @@ to only few.
In output clauses, string and character literals and quasiliterals, a space
token denotes a space.
-.SS Text
-
-Query material which is not escaped by the special character @ is
-literal text, which matches input character for character. Text which occurs at
+.SS* Text
+Query material which is not escaped by the special character
+.code @
+is literal text, which matches input character for character. Text which occurs at
the beginning of a line matches the beginning of a line. Text which starts in
the middle of a line, other than following a variable, must match exactly at
the current position, where the previous match left off. Moreover, if the text
@@ -456,102 +899,141 @@ query. However, a query may leave unmatched lines.
In the following example, the query matches the text, even though
the text has an extra line.
-
- Query: Four score and seven
- years ago our
-
- Text: Four score and seven
- years ago our
- forefathers
+.IP code:
+.cblk
+\ Four score and seven
+ years ago our
+.cble
+
+.IP data:
+.cblk
+\ Four score and seven
+ years ago our
+ forefathers
+.cble
+.PP
In the following example, the query
.B fails
to match the text, because the text has extra material on one
line.
-
- Query: I can carry nearly eighty gigs
- in my head
-
- Text: I can carry nearly eighty gigs of data
- in my head
+.IP code:
+.cblk
+\ I can carry nearly eighty gigs
+ in my head
+.cble
+
+.IP data:
+.cblk
+\ I can carry nearly eighty gigs of data
+ in my head
+.cble
+.PP
Needless to say, if the text has insufficient material relative
to the query, that is a failure also.
To match arbitrary material from the current position to the end
of a line, the "match any sequence of characters, including empty"
-regular expression @/.*/ can be used. Example:
-
- Query: I can carry nearly eighty gigs@/.*/
-
- Text: I can carry nearly eighty gigs of data
+regular expression
+.code @/.*/
+can be used. Example:
+.IP code:
+.cblk
+\ I can carry nearly eighty gigs@/.*/
+.cble
+
+.IP data:
+.cblk
+\ I can carry nearly eighty gigs of data
+.cble
+.PP
In this example, the query matches, since the regular expression
matches the string "of data". (See Regular Expressions section below).
Another way to do this is:
+.IP code:
+.cblk
+\ I can carry nearly eighty gigs@(skip)
+.cble
- Query: I can carry nearly eighty gigs@(skip)
-
-
-.SS Special Characters in Text
-
+.SS* Special Characters in Text
Control characters may be embedded directly in a query (with the exception of
newline characters). An alternative to embedding is to use escape syntax.
The following escapes are supported:
-.IP @\e<newline>
+.meIP >> @\e newline
A backslash immediately followed by a newline introduces a physical line
break without breaking up the logical line. Material following this sequence
continues to be interpreted as a continuation of the previous line, so
that indentation can be introduced to show the continuation without appearing
in the data.
-.IP @\e<space>
+.meIP >> @\e space
A backslash followed by a space encodes a space. This is useful in line
continuations when it is necessary for leading spaces to be preserved.
For instance the two line sequence
- abcd@\
- @\e efg
+.cblk
+ abcd@\
+ @\e efg
+.cble
is equivalent to the line
+.cblk
abcd efg
+.cble
The two spaces before the @\e in the second line are consumed. The
spaces after are preserved.
-.IP @\ea
+.coIP @\ea
Alert character (ASCII 7, BEL).
-.IP @\eb
+.coIP @\eb
Backspace (ASCII 8, BS).
-.IP @\et
+.coIP @\et
Horizontal tab (ASCII 9, HT).
-.IP @\en
+.coIP @\en
Line feed (ASCII 10, LF). Serves as abstract newline on POSIX systems.
-.IP @\ev
+.coIP @\ev
Vertical tab (ASCII 11, VT).
-.IP @\ef
+.coIP @\ef
Form feed (ASCII 12, FF). This character clears the screen on many
kinds of terminals, or ejects a page of text from a line printer.
-.IP @\er
+.coIP @\er
Carriage return (ASCII 13, CR).
-.IP @\ee
+.coIP @\ee
Escape (ASCII 27, ESC)
-.IP @\exHEX
-A @\ex followed by a sequence of hex digits is interpreted as a hexadecimal
-numeric character code. For instance @\ex41 is the ASCII character A.
-.IP @\eOCTAL
-A @\e followed by a sequence of octal digits (0 through 7) is interpreted
-as an octal character code. For instance @\e010 is character 8, same as @\eb.
+.coIP @\exHEX
+A
+.code @\ex
+followed by a sequence of hex digits is interpreted as a hexadecimal
+numeric character code. For instance
+.code @\ex41
+is the ASCII character A.
+.coIP @\eOCTAL
+A
+.code @\e
+followed by a sequence of octal digits (0 through 7) is interpreted
+as an octal character code. For instance
+.code @\e010
+is character 8, same as
+.codn @\eb .
.PP
-Note that if a newline is embedded into a query line with @\en, this
-does not split the line into two; it's embedded into the line and
-thus cannot match anything. However, @\en may be useful in the @(cat)
-directive and in @(output).
+Note that if a newline is embedded into a query line with
+.code @\en,
+this does not split the line into two; it's embedded into the line and thus
+cannot match anything. However,
+.code @\en
+may be useful in the
+.code @(cat)
+directive and
+in
+.codn @(output) .
-.SS Character Handling and International Characters
+.SS* Character Handling and International Characters
.B TXR
represents text internally using wide characters, which are used to represent
@@ -568,7 +1050,11 @@ subset of Unicode.
.B TXR
does not use the localization features of the system library;
its handling of extended characters is not affected by environment variables
-like LANG and L_CTYPE. The program reads and writes only the UTF-8 encoding.
+like
+.code LANG
+and
+.codn L_CTYPE .
+The program reads and writes only the UTF-8 encoding.
If
.B TXR
@@ -599,12 +1085,14 @@ the code U+DC00. On output, this code converts back to a null byte,
as explained in the previous paragraph. By means of this representational
trick, TXR can handle textual data containing null bytes.
-.SS Regular Expression Directives
+.SS* Regular Expression Directives
In place of a piece of text (see section Text above), a regular expression
directive may be used, which has the following syntax:
+.cblk
@/RE/
+.cble
where the RE part enclosed in slashes represents regular expression
syntax (described in the section Regular Expressions below).
@@ -613,10 +1101,12 @@ Long regular expressions can be broken into multiple lines using a
backslash-newline sequence. Whitespace before the sequence or after the
sequence is not significant, so the following two are equivalent:
+.cblk
@/reg \e
ular/
@/regular/
+.cble
There may not be whitespace between the backslash and newline.
@@ -632,7 +1122,9 @@ line.
Even if the regular expression matches the empty string, the match will fail if
the input is empty, or has run out of data. For instance suppose the third line
-of the query is the regular expression @/.*/, but the input is a file which has
+of the query is the regular expression
+.codn @/.*/ ,
+but the input is a file which has
only two lines. This will fail: the data has line for the regular expression to
match. A line containing no characters is not the same thing as the absence of
a line, even though both abstractions imply an absence of characters.
@@ -641,50 +1133,112 @@ Like text which follows a variable, a regular expression directive which
follows a variable has special semantics, discussed in the section Variables
below.
-.SS Variables
+.SS* Variables
Much of the query syntax consists of arbitrary text, which matches file data
character for character. Embedded within the query may be variables and
-directives which are introduced by a @ character. Two consecutive @@
-characters encode a literal @.
+directives which are introduced by a
+.code @
+character. Two consecutive
+.code @@
+characters encode a literal
+.codn @ .
A variable matching or substitution directive is written in one of several
ways:
- @NAME
- @{NAME}
- @*NAME
- @*{NAME}
- @{NAME /RE/}
- @{NAME (FUN [ ARGS ... ])}
- @{NAME NUMBER}
-
-The forms with an * indicate a long match, see Longest Match below.
-The last two forms with the embedded regexp /RE/ or number have special
-semantics, see Positive Match below.
-
-The identifier t cannot be used as a name; it is a reserved symbol which
-denotes the value true. An attempt to use the variable @t will result
-in an exception. The symbol nil can be used as a variable name,
+.cblk
+.mets >> @ sident
+.mets <> @{ bident }
+.mets >> @* sident
+.mets <> @*{ bident }
+.mets >> @{ bident <> / regex /}
+.mets >> @{ bident >> ( fun >> [ arg ... ])}
+.mets >> @{ bident << number }
+.cble
+
+The forms with an
+.code *
+indicate a long match, see Longest Match below.
+The last two forms with the embedded regexp
+.cblk
+.meti <> / regex /
+.cble
+or
+.meta number
+have special semantics, see Positive Match below.
+
+The identifier
+.code t
+cannot be used as a name; it is a reserved symbol which
+denotes the value true. An attempt to use the variable
+.code @t
+will result in an exception. The symbol
+.code nil
+can be used where a variable name is required syntacticaly,
but it has special semantics, described in a section below.
-When the @NAME form is used, the name itself may consist of any combination of
-one or more letters, numbers, and underscores. It may not look like a number,
-so that for instance 123 is not a valid name, but 12A is valid. Case is
-sensitive, so that @FOO is different from @foo, which is different from @Foo.
-
-The braces around a name can be used when material which follows would
-otherwise be interpreted as being part of the name. When a name is enclosed in
-braces, the following additional characters may be used as part of the name:
+A
+.meta sident
+is a "simple identifier" form which is not delimited by
+braces.
+A
+.meta sident
+consists of any combination of
+one or more letters, numbers, and underscores. It may not look like a number,
+so that for instance
+.code 123
+is not a valid
+.metn sident ,
+but
+.code 12A
+is valid. Case is
+sensitive, so that
+.code FOO
+is different from
+.codn foo ,
+which is different from
+.codn Foo .
+
+The braces around an identifier can be used when material which follows would
+otherwise be interpreted as being part of the identifer. When a name is
+enclosed in braces it is a
+.metn bident .
+
+The following additional characters may be used as part of
+.meta bident
+which are not allowed in a
+.metn sident :
+
+.cblk
! $ % & * + - < = > ? \e ^ _ ~
-
-The rule holds that a name cannot look like a number so +123 is not a name,
-but these are valid names: a->b, *xyz*, foo-bar.
-
-The syntax @FOO_bar introduces the name "FOO_bar", whereas @{FOO}_bar means the
-variable named "FOO" followed by the text "_bar". There may be whitespace
-between the @ and the name, or opening brace. Whitespace is also allowed in the
+.cble
+
+The rule still holds that a name cannot look like a number so
+.code +123
+is not a valid
+.meta bident
+but these are valid:
+.codn a->b ,
+.codn *xyz* ,
+.codn foo-bar .
+
+The syntax
+.code @FOO_bar
+introduces the name
+.codn FOO_bar ,
+whereas
+.code @{FOO}_bar
+means the
+variable named
+.str FOO
+followed by the text
+.strn _bar .
+There may be whitespace
+between the
+.code @
+and the name, or opening brace. Whitespace is also allowed in the
interior of the braces. It is not significant.
If a variable has no prior binding, then it specifies a match. The
@@ -694,9 +1248,17 @@ If a variable occurs at the start of a line, it matches some text
at the start of the line. If it occurs at the end of a line, it matches
everything from the current position to the end of the line.
-.SS Negative Match
+.SS* Negative Match
+
+If a variable is one of the plain forms
+
+.cblk
+.mets >> @ sident
+.mets <> @{ bident }
+.mets >> @* sident
+.mets <> @*{ bident }
+.cble
-If a variable is one of the plain forms @NAME, @{NAME}, @*NAME or @*{NAME},
then this is a "negative match". The extent of the matched text (the text
bound to the variable) is determined by looking at what follows the variable,
and ranges from the current position to some position where the following
@@ -708,46 +1270,80 @@ A variable may be followed by a piece of text, a regular expression directive,
a function call, a directive, another variable, or nothing (i.e. occurs at the
end of a line). These cases are discussed in detail below.
-.SS Variable Followed by Nothing
-
+.NP* Variable Followed by Nothing
If the variable is followed by nothing, the negative match extends from the
current position in the data, to the end of the line. Example:
-
- pattern: "a b c @FOO"
- data: "a b c defghijk"
- result: FOO="defghijk"
-
-.SS Variable Followed by Text
-
+.IP code:
+.cblk
+\ a b c @FOO
+.cble
+.IP data:
+.cblk
+\ a b c defghijk
+.cble
+.IP result:
+.cblk
+\ FOO="defghijk"
+.cble
+
+.NP* Variable Followed by Text
For the purposes of determining the negative match, text is defined as a
sequence of literal text and regular expressions, not divided by a directive.
So for instance in this example:
+.cblk
@a:@/foo/bcd e@(maybe)f@(end)
+.cble
+.PP
-the variable @a is considered to be followed by ":@/foo/bcd e".
+the variable @a is considered to be followed by
+.strn ":@/foo/bcd e" .
If a variable is followed by text, then the extent of the negative match is
determined by searching for the first occurrence of that text within the line,
-starting at the current position.
+starting at the current position.
The variable matches everything between the current position and the matching
position (not including the matching position). Any whitespace which follows
the variable (and is not enclosed inside braces that surround the variable
name) is part of the text. For example:
+.IP code:
+.cblk
+\ a b @FOO e f
+.cble
+.IP data:
+.cblk
+\ a b c d e f
+.cble
+.IP result:
+.cblk
+\ FOO="c d"
+.cble
+.PP
- pattern: "a b @FOO e f"
- data: "a b c d e f"
- result: FOO="c d"
-
-In the above example, the pattern text "a b " matches the
-data "a b ". So when the @FOO variable is processed, the data being
-matched is the remaining "c d e f". The text which follows @FOO
-is " e f". This is found within the data "c d e f" at position 3
-(counting from 0). So positions 0-2 ("c d") constitute the matching
-text which is bound to FOO.
-
-.SS Variable Followed by a Function Call or Directive
+In the above example, the pattern text
+.str "a b "
+matches the
+data
+.strn "a b " .
+So when the
+.code @FOO
+variable is processed, the data being
+matched is the remaining
+.strn "c d e f" .
+The text which follows
+.code @FOO
+is
+.strn " e f" .
+This is found within the data
+.str "c d e f"
+at position 3 (counting from 0). So positions 0-2
+.cblk
+("c d")
+.cble
+constitute the matching text which is bound to FOO.
+
+.NP* Variable Followed by a Function Call or Directive
If the variable is followed by a function call, or a directive, the extent is
determined by scanning the text for the first position where a match occurs
@@ -756,25 +1352,39 @@ see FUNCTIONS.)
For example:
+.cblk
@foo@(bind a "abc")xyz
-
-Here, foo will match the text from the current position to where "xyz"
-occurs, even though there is a @(bind) directive. Furthermore, if
+.cble
+
+Here,
+.code foo
+will match the text from the current position to where
+.str "xyz"
+occurs, even though there is a
+.code @(bind)
+directive. Furthermore, if
more material is added after the xyz, it is part of the search.
Note the difference between the following two:
+.cblk
@foo@/abc/@(func)
@foo@(func)@/abc/
+.cble
In the first example, the variable foo matches the text from the current
-position until the match for the regular expression abc. @(func) is not
-considered when processing @foo. In the second example, the variable foo
-matches the text from the current position until the position whcih matches
+position until the match for the regular expression abc.
+.code @(func)
+is not
+considered when processing
+.codn @foo .
+In the second example, the variable foo
+matches the text from the current position until the position which matches
the function call, followed by a match for the regular expression.
-The entire sequence @(func)@/abc/ is considered.
-
-.SS Consecutive Variables
+The entire sequence
+.code @(func)@/abc/
+is considered.
+.NP* Consecutive Variables
If an unbound variable specified a fixed-width match or a regular expression,
then the issue of consecutive variables does not arise. Such a variable
consumes text regardless of any context which follows it.
@@ -784,30 +1394,61 @@ variable? The behavior depends on the nature of the other variable.
If the other variable also has no modifier, this is a semantic error which
will cause the query to fail. A diagnostic message will be issued, unless
-operating in quiet mode via -q. The reason is that there is no way to bind two
+operating in quiet mode via
+.codn -q .
+The reason is that there is no way to bind two
consecutive variables to an extent of text; this is an ambiguous situation,
since there is no matching criterion for dividing the text between two
-variables. (In theory, a repetition of the same variable, like @FOO@FOO, could
-find a solution by dividing the match extent in half, which would work only in
-the case when it contains an even number of characters. This behavior seems to
-have dubious value).
+variables. (In theory, a repetition of the same variable, like
+.codn @FOO@FOO ,
+could find a solution by dividing the match extent in half, which would work
+only in the case when it contains an even number of characters. This behavior
+seems to have dubious value).
An unbound variable may be followed by one which is bound. The bound
variable is replaced by the text which it denotes, and the logic proceeds
accordingly. Variables are never bound to regular expressions, so
the regular expression match does not arise in this case.
-The @* syntax for longest match is available. Example:
-
- pattern: "@FOO:@BAR@FOO"
- data: "xyz:defxyz"
- result: FOO=xyz, BAR=def
+The
+.code @*
+syntax for longest match is available. Example:
+.IP code:
+.cblk
+\ @FOO:@BAR@FOO
+.cble
+.IP data:
+.cblk
+\ xyz:defxyz
+.cble
+.IP result:
+.cblk
+\ FOO=xyz, BAR=def
+.cble
+.PP
-Here, FOO is matched with "xyz", based on the delimiting around the
+Here,
+.code FOO
+is matched with
+.strn "xyz" ,
+based on the delimiting around the
colon. The colon in the pattern then matches the colon in the data,
-so that BAR is considered for matching against "defxyz".
-BAR is followed by FOO, which is already bound to "xyz".
-Thus "xyz" is located in the "defxyz" data following "def",
-and so BAR is bound to "def".
+so that
+.code BAR
+is considered for matching against
+.strn "defxyz" .
+.code BAR
+is followed by
+.codn FOO ,
+which is already bound to
+.strn "xyz" .
+Thus
+.str "xyz"
+is located in the
+.str "defxyz"
+data following
+.strn "def" ,
+and so BAR is bound to
+.strn "def" .
If an unbound variable is followed by a variable which is bound to a list, or
nested list, then each character string in the list is tried in turn to produce
@@ -821,84 +1462,164 @@ bound: it is a matching failure. If the search succeeds, than the first
variable is bound to the text which is skipped by the search. The second
variable is bound to the text matched by the regular expression or function.
Examples:
+.IP code:
+.cblk
+\ @foo@{bar /abc/}
+.cble
+.IP data:
+.cblk
+\ xyz@#abc
+.cble
+.IP result:
+.cblk
+\ foo="xyz@#", BAR="abc"
+.cble
+.PP
- pattern: "@foo@{bar /abc/}"
- data: "xyz@#abc"
- result: foo="xyz@#", BAR="abc"
-
-
-.SS Consecutive Variables Via Directive
-
+.NP* Consecutive Variables Via Directive
Two variables can be de facto consecutive in a manner shown in the
following example:
+.cblk
@var1@(all)@var2@(end)
+.cble
This is treated just like the variable followed by directive. No semantic
-error is identified, even if both variables are unbound. Here, @var2
-@var2 matches everything at the current position, and so @var1 ends up
-bound to the empty string.
-
-Example 1: b matches at position 0 and a gets nothing:
+error is identified, even if both variables are unbound. Here,
+.code @var2
+matches everything at the current position, and so
+.code @var1
+ends up bound to the empty string.
- pattern: "@a@(all)@b@(end)"
- data: "abc"
- result: a=""
- b="abc"
+Example 1:
+.code b
+matches at position 0 and a gets nothing:
+.IP code:
+.cblk
+\ @a@(all)@b@(end)
+.cble
+.IP data:
+.cblk
+\ abc
+.cble
+.IP result:
+.cblk
+\ a=""
+ b="abc"
+.cble
+.PP
-Example 2: *a specifies longest match (see Longest Match below), and so a gets
+Example 2:
+.code *a
+specifies longest match (see Longest Match below), and so a gets
everything:
+.IP code:
+.cblk
+\ @*a@(all)@b@(end)
+.cble
+.IP data:
+.cblk
+\ abc
+.cble
+.IP result:
+.cblk
+\ a="abc"
+ b=""
+.cble
+.PP
- pattern: "@*a@(all)@b@(end)"
- data: "abc"
- result: a="abc"
- b=""
-
-
-
-.SS Longest Match
-
+.NP* Longest Match
The closest-match behavior for the negative match can be overridden to longest
match behavior. A special syntax is provided for this: an asterisk between the
-@ and the variable, e.g:
-
- pattern: "a @*{FOO}cd"
- data: "a b cdcdcdcd"
- result: FOO="b cdcdcd"
-
- pattern: "a @{FOO}cd"
- data: "a b cdcdcd"
- result: FOO="b "
-
-In the former example, the match extends to the rightmost occurrence of "cd",
-and so FOO receives "b cdcdcd". In the latter example, the *
+.code @
+and the variable, e.g:
+.IP code:
+.cblk
+\ a @*{FOO}cd
+.cble
+.IP data:
+.cblk
+\ a b cdcdcdcd
+.cble
+.IP result:
+.cblk
+\ FOO="b cdcdcd"
+.cble
+.PP
+.IP code:
+.cblk
+\ a @{FOO}cd
+.cble
+.IP data:
+.cblk
+\ a b cdcdcd
+.cble
+.IP result:
+.cblk
+\ FOO="b "
+ b=""
+.cble
+
+In the former example, the match extends to the rightmost occurrence of
+.strn "cd" ,
+and so
+.code FOO
+receives
+.strn "b cdcdcd" .
+In the latter example, the
+.code *
syntax isn't used, and so a leftmost match takes place. The extent
-covers only the "b ", stopping at the first "cd" occurrence.
+covers only the
+.strn "b " ,
+stopping at the first
+.str "cd"
+occurrence.
-.SS Positive Match
+.SS* Positive Match
There are syntax variants of variable syntax which have an embedded expression
enclosed with the variable in braces:
- @{NAME /RE/}
- @{NAME (FUN [ARGS ...])}
- @{NAME NUMBER}
+.cblk
+.mets >> @{ bident <> / regex /}
+.mets >> @{ bident >> ( fun >> [args ...])}
+.mets >> @{ bident << number }
+.cble
These specify a variable binding that is driven by a positive match derived
from a regular expression, function or character count, rather than from
trailing material (which is regarded as a "negative" match, since the
variable is bound to material which is
.B skipped
-in order to match the trailing material). In the /RE/ form, the match
+in order to match the trailing material). In the
+.cblk
+.meti <> / regex /
+.cble
+form, the match
extends over all characters from the current position which match
-the regular expression RE. (see Regular Expressions section below).
-In the (FUN [ARGS ...]) form, the match extends over characters which
+the regular expression
+.metn regex .
+(see Regular Expressions section below).
+In the
+.cblk
+.meti >> ( fun >> [ args ...])
+.cble
+form, the match extends over characters which
are matched by the call to the function, if the call
-succeeds. Thus @{x (y z w)} is just like @(y z w), except that the region of
-text skipped over by @(y z w) is also bound to the variable x.
+succeeds. Thus
+.code @{x (y z w)}
+is just like
+.codn "@(y z w)" ,
+except that the region of
+text skipped over by
+.code @(y z w)
+is also bound to the variable
+.codn x .
See FUNCTIONS below.
-In the NUMBER form, the match processes a field of text which
+In the
+.meta number
+form, the match processes a field of text which
consists of the specified number of characters, which must be non-negative
number. If the data line doesn't have that many characters starting at the
current position, the match fails. A match for zero characters produces an
@@ -911,217 +1632,490 @@ This syntax is processed without consideration of what other
syntax follows. A positive match may be directly followed by an unbound
variable.
-.SS Symbol nil as a Variable
+.coSS* Special Symbols @ nil and @ t
-If the symbol nil is used as a variable, it behaves like a variable which
-has no binding. Furthermore, no binding is created. @nil allows the
-variable matching syntax to be used to skip material, in ways different
-from and complementary to @(skip).
+Just like in the Common Lisp language, the names
+.code nil
+and
+.code t
+are special.
-.SS Regular Expressions
+.code nil
+symbol stands for the empty
+list object, an object which marks the end of a list, and boolean false. It is
+synonymous with the syntax
+.code ()
+which may be used interchangeably with
+.code nil
+in most constructs.
+
+In TXR Lisp,
+.code nil
+and
+.code t
+cannot be used as variables. When evaluated, they evaluate to themselves.
+
+In the TXR pattern language,
+.code nil
+can be used in the variable binding syntax, but does not create a binding;
+it has a special meaning. It allows the variable matching syntax to be used to
+skip material, in ways similar to the
+.codn skip
+directive.
+
+The
+.code nil
+symbol is also used as a
+.code block
+name, both in the TXR pattern language and in TXR Lisp.
+A block named
+.code nil
+is considered to be anonymous.
+
+.SS* Keyword Symbols
+
+Names whose names begin with the
+.code :
+character are keyword symbols. These also
+may not be used as variables either and stand for themselves. Keywords are
+useful for labeling information and situations.
+.SS* Regular Expressions
Regular expressions are a language for specifying sets of character strings.
Through the use of pattern matching elements, regular expression is
able to denote an infinite set of texts.
.B TXR
contains an original implementation of regular expressions, which
supports the following syntax:
-.IP .
+.coIP .
(period) is a "wildcard" that matches any character.
-.IP []
+.coIP []
Character class: matches a single character, from the set specified by
special syntax written between the square brackets.
-Supports basic regexp character class syntax; no POSIX
-notation like [:digit:]. The regex tokens \es, \ed and \ew are
-permitted in character classes, but not their complementing counterparts.
+This supports basic regexp character class syntax. POSIX
+notation like
+.code [:digit:]
+is nto supported.
+The regex tokens
+.codn \es ,
+.code \ed
+and
+.code \ew
+are permitted in character classes, but not their complementing counterparts.
These tokens simply contribute their characters to the class.
-The class [a-zA-Z] means match an uppercase
-or lowercase letter; the class [0-9a-f] means match a digit or
-a lowercase letter; the class [^0-9] means match a non-digit, et cetera.
+The class
+.code [a-zA-Z]
+means match an uppercase
+or lowercase letter; the class
+.code [0-9a-f]
+means match a digit or
+a lowercase letter; the class
+.code [^0-9]
+means match a non-digit, and so forth.
There are no locale-specific behaviors in TXR regular expressions;
-[A-Z] denotes an ASCII/Unicode range of characters.
-The class [\ed.] means match a digit or the period character.
-A ] or - can be used within a character class, but must be escaped
-with a backslash. A ^ in the first position denotes a complemented
+.code [A-Z]
+denotes an ASCII/Unicode range of characters.
+The class
+.code [\ed.]
+means match a digit or the period character.
+A
+.code ]
+or
+.code -
+can be used within a character class, but must be escaped
+with a backslash. A
+.code ^
+in the first position denotes a complemented
class, unless it is escaped by backslash. In any other position, it denotes
itself. Two backslashes code for one backslash. So for instance
-[\e[\e-] means match a [ or - character, [^^] means match any character other
-than ^, and [\e^\e\e] means match either a ^ or a backslash. Regex operators
-such as *, + and & appearing in a character class represent ordinary
-characters. The characters -, ] and ^ occurring outside of a character class
-are ordinary. Unescaped / characters can appear within a character class. The
-empty character class [] matches no character at all, and its complement [^]
-matches any character, and is treated as a synonym for the . (period) wildcard
-operator.
-.IP "\es, \ew and \ed"
+.code [\e[\e-]
+means match a
+.code [
+or
+.code -
+character,
+.code [^^]
+means match any character other
+than
+.codn ^ ,
+and
+.code [\e^\e\e]
+means match either a
+.code ^
+or a backslash. Regex operators
+such as
+.codn * ,
+.code +
+and
+.code &
+appearing in a character class represent ordinary
+characters. The characters
+.codn - ,
+.code ]
+and
+.code ^
+occurring outside of a character class
+are ordinary. Unescaped
+.code /
+characters can appear within a character class. The
+empty character class
+.code []
+matches no character at all, and its complement
+.code [^]
+matches any character, and is treated as a synonym for the
+.code .
+(period) wildcard operator.
+.coIP "\es, \ew and \ed"
These regex tokens each match a single character.
-The \es regex token matches a wide variety of ASCII whitespace characters
-and Unicode spaces. The \ew token matches alphabetic word characters; it
-is equivalent to the character class [A-Za-z_]. The \ed token matches
-a digit, and is equivalent to [0-9].
-.IP "\eS, \eW and \eD"
-These regex tokens are the complemented counterparts of \es, \ew and \ed.
-The \eS token matches all those characters which \es does not match,
-\eW matches all characters that \ew does not match and \eD matches nondigits.
-.IP empty
+The
+.code \es
+regex token matches a wide variety of ASCII whitespace characters
+and Unicode spaces. The
+.code \ew
+token matches alphabetic word characters; it
+is equivalent to the character class
+.codn [A-Za-z_] .
+The
+.code \ed
+token matches a digit, and is equivalent to
+.codn [0-9] .
+.dcoIP "\eS, \eW and \eD"
+These regex tokens are the complemented counterparts of
+.codn \es ,
+.code \ew
+and
+.codn \ed .
+The
+.code \eS
+token matches all those characters which
+.code \es
+does not match,
+.code \eW
+matches all characters that
+.code \ew
+does not match and
+.code \eD
+matches nondigits.
+.coIP empty
An empty expression is a regular expression. It represents the set of strings
consisting of the empty string; i.e. it matches just the empty string. The
empty regex can appear alone as a full regular expression (for instance the
.B TXR
-syntax @// with nothing between the slashes)
+syntax
+.code @//
+with nothing between the slashes)
and can also be passed as a subexpression to operators, though this
may require the use of parentheses to make the empty regex explicit. For
-example, the expression a| means: match either a, or nothing. The forms
-* and (*) are syntax errors; though not useful, the correct way to match the
-empty expression zero or more times is the syntax ()*.
-.IP nomatch
+example, the expression
+.code a|
+means: match either
+.codn a ,
+or nothing. The forms
+.code *
+and
+.code (*)
+are syntax errors; though not useful, the correct way to match the
+empty expression zero or more times is the syntax
+.codn ()* .
+.coIP nomatch
The nomatch regular expression represents the
empty set: it matches no strings at all, not even the empty string.
There is no dedicated syntax to directly express nomatch in the regex language.
-However, the empty character class [] is equivalent to nomatch, and may be
+However, the empty character class
+.code []
+is equivalent to nomatch, and may be
considered to be a notation for it. Other representations of nomatch are
-possible: for instance, the regex ~.* which is the complement of the regex that
+possible: for instance, the regex
+.code ~.*
+which is the complement of the regex that
denotes the set of all possible strings, and thus denotes the empty set. A
nomatch has uses; for instance, it can be used to temporarily "comment out"
-regular expressions. The regex ([]abc|xyz) is equivalent to (xyz), since the
-[]abc branch cannot match anything. Using [] to "block" a subexpression allows
+regular expressions. The regex
+.code ([]abc|xyz)
+is equivalent to
+.codn (xyz) ,
+since the
+.code []abc
+branch cannot match anything. Using
+.code []
+to "block" a subexpression allows
you to leave it in place, then enable it later by removing the "block".
-.IP (R)
-If R is a regular expression, then so is (R).
+.coIP (R)
+If
+.code R
+is a regular expression, then so is
+.code (R).
The contents of parentheses denote one regular expression unit, so that for
-instance in (RE)*, the * operator applies to the entire parenthesized group.
-The syntax () is valid and equivalent to the empty regular expression.
-.IP R?
-optionally match the preceding regular expression R.
-.IP R*
-match the expression R zero or more times. This
+instance in
+.codn (RE)* ,
+the
+.code *
+operator applies to the entire parenthesized group.
+The syntax
+.code ()
+is valid and equivalent to the empty regular expression.
+.coIP R?
+optionally match the preceding regular expression
+.codn R .
+.coIP R*
+match the expression
+.code R
+zero or more times. This
operator is sometimes called the "Kleene star", or "Kleene closure".
The Kleene closure favors the longest match. Roughly speaking, if there are two
-or more ways in which R1*R2 can match, than that match occurs in which
-R1* matches the longest possible text.
-.IP R+
-match the preceding expression R one or more times.
-Like R*, this favors the longest possible match: R+ is equivalent to RR*.
-.IP R1%R2
-match R1 zero or more times, then match R2. If this match can occur in
-more than one way, then it occurs such that R1 is matched the fewest
-number of times, which is opposite from the behavior of R1*R2.
-Repetitions of R1 terminate at the earliest
-point in the text where a non-empty match for R2 occurs. Because
-it favors shorter matches, % is termed a non-greedy operator. If R2 is the
-empty expression, or equivalent to it, then R1%R2 reduces to R1*. So for
-instance (R%) is equivalent to (R*), since the missing right operand is
+or more ways in which
+.code R1*R2
+can match, than that match occurs in which
+.code R1*
+matches the longest possible text.
+.coIP R+
+match the preceding expression
+.code R
+one or more times. Like
+.codn R* ,
+this favors the longest possible match:
+.code R+
+is equivalent to
+.codn RR* .
+.coIP R1%R2
+match
+.code R1
+zero or more times, then match
+.codn R2 .
+If this match can occur in
+more than one way, then it occurs such that
+.code R1
+is matched the fewest
+number of times, which is opposite from the behavior of
+.codn R1*R2 .
+Repetitions of
+.code R1
+terminate at the earliest
+point in the text where a non-empty match for
+.code R2
+occurs. Because
+it favors shorter matches,
+.code %
+is termed a non-greedy operator. If
+.code R2
+is the empty expression, or equivalent to it, then
+.code R1%R2
+reduces to
+. codn R1* .
+So for
+instance
+.code (R%)
+is equivalent to
+.codn (R*) ,
+since the missing right operand is
interpreted as the empty regex. Note that whereas the expression
-(R1*R2) is equivalent to (R1*)R2, the expression (R1%R2) is
+.code (R1*R2)
+is equivalent to
+.codn (R1*)R2 ,
+the expression
+.code (R1%R2)
+is
.B not
-equivalent to (R1%)R2.
-.IP ~R
-match the opposite of the following expression R; i.e. match exactly
-those texts that R does not match. This operator is called complement,
+equivalent to
+.codn (R1%)R2 .
+.coIP ~R
+match the opposite of the following expression
+.codn R ;
+that is, match exactly
+those texts that
+.code R
+does not match. This operator is called complement,
or logical not.
-.IP R1R2
+.coIP R1R2
Two consecutive regular expressions denote catenation:
the left expression must match, and then the right.
-.IP R1|R2
-match either the expression R1 or R2. This operator is known by
+.coIP R1|R2
+match either the expression
+.code R1
+or
+.codn R2 .
+This operator is known by
a number of names: union, logical or, disjunction, branch, or alternative.
-.IP R1&R2
-match both the expression R1 and R2 simultaneously; i.e. the
+.coIP R1&R2
+match both the expression
+.code R1
+and
+.code R2
+simultaneously; i.e. the
matching text must be one of the texts which are in the intersection of the set
-of texts matched by R1 and the set matched by R2. This operator is called
-intersection, logical and, or conjunction.
+of texts matched by
+.code R1
+and the set matched by
+.codn R2 .
+This operator is called intersection, logical and, or conjunction.
.PP
Any escaped character which does not fall into the above escaping conventions,
or any unescaped character which is not a regular expression operator, denotes
one-position match of that character itself.
-Any of the special characters, including the delimiting /, can be escaped with
-a backslash to suppress its meaning and denote the character itself.
+Any of the special characters, including the delimiting
+.codn / ,
+can be escaped with a backslash to suppress its meaning and denote the
+character itself.
Furthermore, all of the same escapes as are described in the section Special
Characters in Text above are supported - the difference is that in regular
-expressions, the @ character is not required, so for example a tab is coded as
-\et rather than @\et. Octal and hex character escapes can be optionally
+expressions, the
+.code @
+character is not required, so for example a tab is coded as
+.code \et
+rather than
+.codn @\et .
+Octal and hex character escapes can be optionally
terminated by a semicolon, which is useful if the following characters are
octal or hex digits not intended to be part of the escape.
-
-Precedence table, highest to lowest:
+.IP "Precedence table, highest to lowest:"
.TS
tab(!);
l l l.
-operators!class!associativity
-(R) []!primary!
-R? R+ R* R%...!postfix!left-to-right
-R1R2!catenation!left-to-right
-~R ...%R!unary!right-to-left
-R1&R2!intersection!left-to-right
-R1|R2!union!left-to-right
+Operators!Class!Associativity
+\f[4](R) []\f[]!primary!
+\f[4]R? R+ R* R%...\f[]!postfix!left-to-right
+\f[4]R1R2\f[]!catenation!left-to-right
+\f[4]~R ...%R\f[]\f[]\f[]!unary!right-to-left
+\f[4]R1&R2\f[]!intersection!left-to-right
+\f[4]R1|R2\f[]!union!left-to-right
.TE
+.PP
-The % operator is like a postfix operator with respect to its left
+The
+.code %
+operator is like a postfix operator with respect to its left
operand, but like a unary operator with respect to its right operand.
-Thus a~b%c~d is a(~(b%(c(~d)))), demonstrating right-to-left associativity,
-where all of b% may be regarded as a unary operator being applied to c~d.
-Similarly, a?*+%b means (((a?)*)+)%b, where the trailing %b behaves
-like a postfix operator.
+Thus
+.code a~b%c~d
+is
+.cblk
+a(~(b%(c(~d))))
+.cble
+, demonstrating right-to-left associativity,
+where all of
+.code b%
+may be regarded as a unary operator being applied to
+.codn c~d .
+Similarly,
+.code a?*+%b
+means
+.codn (((a?)*)+)%b ,
+where the trailing
+.code %b
+behaves like a postfix operator.
In
.B TXR,
regular expression matches do not span multiple lines. The regex language has
-no feature for multi-line matching. However, the @(freeform) directive
+no feature for multi-line matching. However, the
+.code @(freeform)
+directive
allows the remaining portion of the input to be treated as one string
in which line terminators appear as explicit characters. Regular expressions
may freely match through this sequence.
It's possible for a regular expression to match an empty string.
-For instance, if the next input character is z, facing a
-the regular expression /a?/, there is a zero-character match:
+For instance, if the next input character is
+.codn z ,
+facing a
+the regular expression
+.codn /a?/ ,
+there is a zero-character match:
the regular expression's state machine can reach an acceptance
state without consuming any characters. Examples:
+.IP code:
+.cblk
+\ @A@/a?/@/.*/
+.cble
+.IP data:
+.cblk
+\ zzzzz
+.cble
+.IP result:
+.cblk
+\ A=""
+.cble
+.PP
- pattern: @A@/a?/@/.*/
- data: zzzzz
- result: A=""
-
- pattern: @{A /a?/}@B
- data: zzzzz
- result: A="", B="zzzz"
+.IP code:
+.cblk
+\ @{A /a?/}@B
+.cble
+.IP data:
+.cblk
+\ zzzzz
+.cble
+.IP result:
+.cblk
+\ A="", B="zzzz"
+.cble
+.PP
- pattern: @*A@/a?/
- data: zzzzz
- result: A="zzzzz"
+.IP code:
+.cblk
+\ @*A@/a?/
+.cble
+.IP data:
+.cblk
+\ zzzzz
+.cble
+.IP result:
+.cblk
+\ A="zzzzz"
+.cble
+.PP
-In the first example, variable @A is followed by a regular expression
-which can match an empty string. The expression faces the letter "z"
+In the first example, variable
+.code @A
+is followed by a regular expression
+which can match an empty string. The expression faces the letter
+.code "z"
at position 0 in the data line. A zero-character match occurs there,
-therefore the variable A takes on the empty string. The @/.*/ regular
-expression then consumes the line.
-
-Similarly, in the second example, the /a?/ regular expression faces
-a "z", and thus yields an empty string which is bound to A. Variable
-@B consumes the entire line.
+therefore the variable
+.code A
+takes on the empty string. The
+.code @/.*/
+regular expression then consumes the line.
+
+Similarly, in the second example, the
+.code /a?/
+regular expression faces a
+.codn "z" ,
+and thus yields an empty string which is bound to
+.codn A .
+Variable
+.code @B
+consumes the entire line.
The third example requests the longest match for the variable binding.
Thus, a search takes place for the rightmost position where the
regular expression matches. The regular expression matches anywhere,
including the empty string after the last character, which is
-the rightmost place. Thus variable A fetches the entire line.
+the rightmost place. Thus variable
+.code A
+fetches the entire line.
For additional information about the advanced regular expression
operators, NOTES ON EXOTIC REGULAR EXPRESSIONS below.
-.SS Directives
-
+.SS* Directives
The general syntax of a directive is:
- @EXPR
+.cblk
+.mets >> @ expr
+.cble
-where expr is a parenthesized list of subexpressions. A subexpression
+where
+.meta expr
+stands for a parenthesized list of subexpressions. A subexpression
is a symbol, number, string literal, character literal, quasiliteral, regular
expression, or a parenthesized expression. So, examples of syntactically valid
directives are:
+.cblk
@(banana)
@(a b c (d e f))
@@ -1133,85 +2127,138 @@ directives are:
@(a #/[a-z]*/ b)
@(_ `@file.txt`)
-
-A symbol is lexically the same thing as a variable name (the type enclosed
-in braces in the @{NAME} syntax) and the same rules apply: it can consist
-of all the same characters, and must not look like a number. Tokens that look
-like numbers are treated as numbers.
-
-.SS Special Symbols
-
-Just like in the programming language Lisp, the names nil and t cannot be used
-as variables. They always represent themselves, and have many uses, internal to
-the program as well as externally visible. The nil symbol stands for the empty
-list object, an object which marks the end of a list, and boolean false. It is
-synonymous with the syntax () which may be used interchangeably with nil in
-most constructs.
-
-.SS Keyword Symbols
-
-Names whose names begin with the : character are keyword symbols. These also
-may not be used as variables either and stand for themselves. Keywords are
-useful for labeling information and situations.
-
-.SS Character Literals
-
-Character literals are introduced by the #\e syntax, which is either
-followed by a character name, the letter x followed by hex digits,
-the letter o followed by octal digits, or a single character. Valid character
-names are: nul, alarm, backspace, tab, linefeed, newline, vtab, page, return,
-esc, space and pnul. This convention for character literals is similar to that
-of the Scheme language. Note that #\elinefeed and #\enewline are the same
-character. The #\epnul character is specific to TXR and denotes the U+DC00
+.cble
+
+A symbol has the same lexical form as a
+.meta bident
+in the syntax
+.cblk
+.meti <> @{ bident }
+.cble
+introduced earlier. It must not be a number;
+tokens that look like numbers are treated as numbers and not symbols.
+
+.SS* Character Literals
+
+Character literals are introduced by the
+.code #\e
+syntax, which is either
+followed by a character name, the letter
+.code x
+followed by hex digits,
+the letter
+.code o
+followed by octal digits, or a single character. Valid character
+names are:
+
+.cblk
+ nul linefeed return
+ alarm newline esc
+ backspace vtab space
+ tab page pnul
+.cble
+
+For instance
+.code #\eesc
+denotes the escape character.
+
+This convention for character literals is similar to that
+of the Scheme language. Note that
+.code #\elinefeed
+and
+.code #\enewline
+are the same
+character. The
+.code #\epnul
+character is specific to TXR and denotes the
+.code U+DC00
code in Unicode; the name stands for "pseudo-null", which is related to
its special function. For more information about this, see the section
"Character Handling and International Characters".
-.SS String Literals
+.SS* String Literals
String literals are delimited by double quote respectively.
-A double quote within a string literal is encoded using \e"
-and a backslash is encoded as \e\e. Backslash escapes like \en and \et
-are recognized, as are hexadecimal escapes like \exFF or \exxabc and octal
-escapes like \e123. Ambiguity between an escape and subsequent
-text can be resolved by using trailing semicolon delimiter: "\exabc;d" is a
-string consisting of the character U+0ABC followed by "d". The semicolon
+A double quote within a string literal is encoded using
+.cblk
+\e"
+.cble
+and a backslash is encoded as
+.codn \e\e .
+Backslash escapes like
+.code \en
+and
+.code \et
+are recognized, as are hexadecimal escapes like
+.code \exFF
+or
+.code \exxabc
+and octal
+escapes like
+.codn \e123 .
+Ambiguity between an escape and subsequent
+text can be resolved by using trailing semicolon delimiter:
+.str "\exabc;d"
+is a string consisting of the character
+.code "U+0ABC"
+followed by
+.strn "d" .
+The semicolon
delimiter disappears. To write a literal semicolon immediately after a hex
or octal escape, write two semicolons, the first of which will be interpreted
-as a delimiter. Thus, "\ex21;;" represents "!;".
+as a delimiter. Thus,
+.str "\ex21;;"
+represents
+.strn "!;" .
If the line ends in the middle of a literal, it is an error, unless the
last character is a backslash. This backslash is a special escape which does
not denote a character; rather, it indicates that the string literal continues
on the next line. The backslash is deleted, along with whitespace which
immediately precedes it, as well as leading whitespace in the following line.
-The escape sequence "\e " (backslash space) can be used to encode a
-significant space.
+The escape sequence
+.str "\e "
+(backslash space) can be used to encode a significant space.
Example:
- "foo \e
- bar"
+.cblk
+ "foo \e
+ bar"
- "foo \e
- \ bar"
+ "foo \e
+ \ bar"
- "foo\ \e
- bar"
+ "foo\ \e
+ bar"
+.cble
-The first string literal is the string "foobar". The second two are "foo bar".
+The first string literal is the string
+.strn "foobar" .
+The second two are
+.strn "foo bar" .
-.SS Word List Literals
+.SS* Word List Literals
A word list literal (WLL) provides a convenient way to write a list of strings
when such a list can be given as whitespace-delimited words.
-There are two flavors of the WLL: the regular WLL which begins with #" (hash,
-double-quote) and the splicing list literal which begins with #*" (hash, star,
-double-quote).
+There are two flavors of the WLL: the regular WLL which begins with
+.cblk
+#"
+.cble
+(hash, double-quote) and the splicing list literal which begins with
+.cblk
+#*"
+.cble
+(hash, star, double-quote).
Both types are terminated by a double quote, which may be escaped
-as \e" in order to include it as a character. All the escaping conventions
+as
+.cblk
+\e"
+.cble
+in order to include it as a character. All the escaping conventions
used in string literals can be used in word literals.
Unlike in string literals, whitespace (tabs, spaces and newlines) is not
@@ -1221,12 +2268,14 @@ escaped with a backslash in order to include it as a literal character.
Example:
+.cblk
#"abc def ghi" --> notates ("abc" "def" "ghi")
#"abc def
ghi" --> notates ("abc" "def" "ghi")
#"abc\ def ghi" --> notates ("abc def" "ghi")
+.cble
A splicing word literal differs from a word literal in that it does not
produce a list of string literals, but rather it produces a sequence of string
@@ -1234,23 +2283,42 @@ literals that is merged into the surrounding syntax.
Example:
+.cblk
(1 2 3 #*"abc def" 4 5 #"abc def")
--> (1 2 3 "abc" "def" 4 5 ("abc" "def"))
+.cble
The regular WLL produced a single list object, but the splicing
WLL expanded into multiple string literal objects.
-.SS String Quasiliterals
+.SS* String Quasiliterals
Quasiliterals are similar to string literals, except that they may
-contain variable references denoted by the usual @ syntax. The quasiliteral
+contain variable references denoted by the usual
+.code @
+syntax. The quasiliteral
represents a string formed by substituting the values of those variables
-into the literal template. If a is bound to "apple" and b to "banana",
-the quasiliteral `one @a and two @{b}s` represents the string
-"one apple and two bananas". A backquote escaped by a backslash represents
-itself, and two consecutive @ characters code for a literal @.
-There is no \e@ escape. Quasiliterals support the full output variable
+into the literal template. If
+.code a
+is bound to
+.str "apple"
+and
+.code b
+to
+.strn "banana" ,
+the quasiliteral
+.code `one @a and two @{b}s`
+represents the string
+.strn "one apple and two bananas" .
+A backquote escaped by a backslash represents
+itself, and two consecutive
+.code @
+characters code for a literal
+.codn @ .
+There is no
+.code \e@
+escape. Quasiliterals support the full output variable
syntax. Expressions within variables substitutions follow the evaluation rules
of TXR Lisp when the quasiliteral occurs in TXR Lisp, and the rules of
the TXR pattern language when the quasiliteral occurs in the pattern language.
@@ -1258,7 +2326,7 @@ the TXR pattern language when the quasiliteral occurs in the pattern language.
Quasiliterals can be split into multiple lines in the same way as ordinary
string literals.
-.SS Quasiword List Literals
+.SS* Quasiword List Literals
The quasiword list literals (QLL-s) are to quasiliterals what WLL-s are to
ordinary literals. (See the above section Word List Literals.)
@@ -1267,12 +2335,16 @@ A QLL combines the convenience of the WLL
with the power of quasistrings.
Just as in the case of WLL-s, there are two flavors of the
-QLL: the regular QLL which begins with #`
-(hash, backquote) and the splicing list literal which begins with #*` (hash,
-star, backquote).
+QLL: the regular QLL which begins with
+.code #`
+\ (hash, backquote) and the splicing list literal which begins with
+.code #*`
+\ (hash, star, backquote).
Both types are terminated by a backquote, which may be escaped
-as \e` in order to include it as a character. All the escaping conventions
+as
+.code \e`
+\ in order to include it as a character. All the escaping conventions
used in quasiliterals can be used in QLL.
Unlike in quasiliterals, whitespace (tabs, spaces and newlines) is not
@@ -1280,64 +2352,102 @@ significant in QLL: it separates words. Whitespace may be
escaped with a backslash in order to include it as a literal character.
Note that the delimiting into words is done before the variable
-substitution. If the variable a contains spaces, then #`@a` nevertheless
-expands into a list of one item: the string derived from a.
+substitution. If the variable a contains spaces, then
+.code #`@a`
+nevertheless
+expands into a list of one item: the string derived from
+.codn a .
-Example:
+Examples:
+.cblk
#`abc @a ghi` --> notates (`abc` `@a` `ghi`)
#`abc @d@e@f
ghi` --> notates (`abc` `@d@e@f` `ghi`)
#`@a\ @b @c` --> notates (`@a @b` `@c`)
+.cble
A splicing QLL differs from an ordinary QLL in that it does not produce a list
of quasiliterals, but rather it produces a sequence of quasiliterals that is
merged into the surrounding syntax.
-.SS Numbers
+.SS* Numbers
TXR supports integers and floating-point numbers.
-An integer constant is made up of digits 0 through 9, optionally preceded by a
-+ or - sign.
+An integer constant is made up of digits
+.code 0
+through
+.codn 9 ,
+optionally preceded by a
+.code +
+or
+.code -
+sign.
Examples:
+.cblk
123
-34
+0
-0
+234483527304983792384729384723234
+.cble
An integer constant can also be specified in hexadecimal using the prefix
-#x followed by an optional sign, followed by hexadecimal digits: 0 through 9
-and the upper or lower case letters A through F:
-
+.code #x
+followed by an optional sign, followed by hexadecimal digits:
+.code 0
+through
+.code 9
+and the upper or lower case letters
+.code A
+through
+.codn F :
+
+.cblk
#xFF ;; 255
#x-ABC ;; -2748
+.cble
-Similarly, octal numbers are supported with the prefix #o followed by
-octal digits:
+Similarly, octal numbers are supported with the prefix
+.code #o
+followed by octal digits:
+.cblk
#o777 ;; 511
+.cble
-and binary numbers can be written with a #b prefix:
+and binary numbers can be written with a
+.code #b
+prefix:
+.cblk
#b1110 ;; 14
+.cble
A floating-point constant is marked by the inclusion of a decimal point, the
exponential "e notation", or both. It is an optional sign, followed
by a mantissa consisting of digits, a decimal point, more digits, and then an
-optional exponential notation consisting of the letter "e" or "E", an optional
-"+" or "-" sign, and then digits indicating the exponent value.
+optional exponential notation consisting of the letter
+.code "e"
+or
+.codn "E" ,
+an optional
+.code +
+or
+.code -
+sign, and then digits indicating the exponent value.
In the mantissa, the digits are not optional. At least one digit must either
precede the decimal point or follow. That is to say, a decimal point by itself
is not a floating-point constant.
Examples:
+.cblk
.123
123.
1E-3
@@ -1346,47 +2456,75 @@ Examples:
9.E19
-.5
+3E+3
+.cble
Examples which are not floating-point constant tokens:
- . (consing dot)
- 123E (the symbol 123E)
- 1.0E- (syntax error: invalid floating point constant)
- 1.0E (syntax error: invalid floating point constant)
- 1.E (1; consing dot; symbol E)
- .e (consing dot followed by symbol e)
+.cblk
+ . ;; consing dot
+ 123E ;; the symbol 123E
+ 1.0E- ;; syntax error: invalid floating point constant
+ 1.0E ;; syntax error: invalid floating point constant
+ 1.E ;; 1; consing dot; symbol E
+ .e ;; consing dot followed by symbol e
+.cble
In TXR there is a special "dotdot" token consisting of two consecutive periods.
An integer constant followed immediately by dotdot is recognized as such; it is
not treated as a floating constant followed by a dot. That is to say,
-123.. does not mean 123. . (floating point 123.0 value followed by dot token).
-It means 123 .. (integer 123 followed by .. token).
-
-Dialect note: unlike in Common Lisp, 123. is not an integer, but the same as
-123.0.
-
-.SS Comments
-
-Comments of the form @; were already covered. Inside directives,
-comments are introduced just by a ; character.
+.code 123..
+does not mean
+.code 123. .
+(floating point
+.code 123.0
+value followed by dot token). It means
+.code 123 ..
+(integer
+.code 123
+followed by
+.code ..
+token).
+
+Dialect note: unlike in Common Lisp,
+.code 123.
+is not an integer, but the floating-point number
+.codn 123.0 .
+
+.SS* Comments
+
+Comments of the form
+.code @;
+were already covered. Inside directives,
+comments are introduced just by a
+.code ;
+character.
Example:
+.cblk
@(foo ; this is a comment
bar ; this is another comment
)
+.cble
-This is equivalent to @(foo bar).
+This is equivalent to
+.codn "@(foo bar)" .
-.SS Directives-driven Syntax
+.SS* Directives-driven Syntax
Some directives not only denote an expression, but are also involved in
surrounding syntax. For instance, the directive
+.cblk
@(collect)
+.cble
not only denotes an expression, but it also introduces a syntactic phrase which
-requires a matching @(end) directive. So in other words, @(collect) is not only
+requires a matching
+.code @(end)
+directive. In other words,
+.code @(collect)
+is not only
an expression, but serves as a kind of token in a higher level phrase structure
grammar.
@@ -1399,7 +2537,9 @@ then it is in a horizontal syntactic and semantic context (character-oriented).
There is an exception: the definition of a horizontal function looks like this:
+.cblk
@(define name (arg))body material@(end)
+.cble
Yet, this is considered one vertical item, which means that it does not match
a line of data. (This is necessary because all horizontal syntax matches
@@ -1411,185 +2551,235 @@ horizontal only but in future releases, these exceptions will be minimized.
A summary of the available directives follows:
-.IP @(eof)
+.coIP @(eof)
Explicitly match the end of file. Fails if unmatched data remains in
the input stream.
-.IP @(eol)
+.coIP @(eol)
Explicitly match the end of line. Fails if the current position is not the
end of a line. Also fails if no data remains (there is no current line).
-.IP @(next)
+.coIP @(next)
Continue matching in another file or other data source.
-.IP @(block)
+.coIP @(block)
Groups together a sequence of directives into a logical name block,
which can be explicitly terminated from within using
-the @(accept) and @(fail) directives.
+the
+.code @(accept)
+and
+.code @(fail)
+directives.
Blocks are discussed in the section BLOCKS below.
-.IP @(skip)
+.coIP @(skip)
Treat the remaining query as a subquery unit, and search the lines (or
characters) of the input file until that subquery matches somewhere. A skip is
also an anonymous block.
-.IP @(trailer)
+.coIP @(trailer)
Treat the remaining query or subquery as a match for a trailing context. That
is to say, if the remainder matches, the data position is not advanced.
-.IP @(freeform)
+.coIP @(freeform)
Treat the remainder of the input as one big string, and apply the following
query line to that string. The newline characters (or custom separators) appear
explicitly in that string.
-.IP @(fuzz)
+.coIP @(fuzz)
The fuzz directive, inspired by the patch utility, specifies a partial
match for some lines.
-.IP @(some)
+.coIP @(some)
Multiple clauses are each applied to the same input. Succeeds if at least one
of the clauses matches the input. The bindings established by earlier
successful clauses are visible to the later clauses.
-.IP @(all)
+.coIP @(all)
Multiple clauses are applied to the same input. Succeeds if and only if each
one of the clauses matches. The clauses are applied in sequence, and evaluation
stops on the first failure. The bindings established by earlier successful
clauses are visible to the later clauses.
-.IP @(none)
+.coIP @(none)
Multiple clauses are applied to the same input. Succeeds if and only if none of
them match. The clauses are applied in sequence, and evaluation stops on the
first success. No bindings are ever produced by this construct.
-.IP @(maybe)
+.coIP @(maybe)
Multiple clauses are applied to the same input. No failure occurs if none of
them match. The bindings established by earlier successful clauses are visible
to the later clauses.
-.IP @(cases)
+.coIP @(cases)
Multiple clauses are applied to the same input. Evaluation stops on the
first successful clause.
-.IP @(require)
+.coIP @(require)
The require directive is similar to the do directive: it evaluates one or more
TXR Lisp expressions. If the result of the rightmost expression is nil,
then require triggers a match failure. See the TXR LISP section far below.
-.IP "@(if), @(elif), @(else)"
+.ccIP @, @(if) @, @(elif) and @ @(else)
The if directive with optional elif and else clauses is a syntactic sugar
-which translates to a combination of @(cases) and @(require)
+which translates to a combination of
+.code @(cases)
+and
+.codn @(require) .
-.IP @(choose)
+.coIP @(choose)
Multiple clauses are applied to the same input. The one whose effect persists
is the one which maximizes or minimizes the length of a particular variable.
-.IP @(empty)
-The @(empty) directive matches the empty string. It is useful in certain
+.coIP @(empty)
+The
+.code @(empty)
+directive matches the empty string. It is useful in certain
situations, such as expressing an empty match in a directive that doesn't
-accept an empty clause. The @(empty) syntax has another meaning in
-@(output) clauses, in conjunction with @(repeat).
-
-.IP "@(define NAME ( ARGUMENTS ...))"
+accept an empty clause. The
+.code @(empty)
+syntax has another meaning in
+.code @(output)
+clauses, in conjunction with
+.codn @(repeat) .
+
+.meIP @(define < name >> ( args ...))
Introduces a function. Functions are discussed in the FUNCTIONS section below.
-.IP @(gather)
+.coIP @(gather)
Searches text for matches for multiple clauses which may occur in arbitrary
order. For convenience, lines of the first clause are treated as separate
clauses.
-.IP @(collect)
+.coIP @(collect)
Search the data for multiple matches of a clause. Collect the
bindings in the clause into lists, which are output as array variables.
-The @(collect) directive is line oriented. It works with a multi-line
-pattern and scans line by line. A similar directive called @(coll)
+The
+.code @(collect)
+directive is line oriented. It works with a multi-line
+pattern and scans line by line. A similar directive called
+.code @(coll)
works within one line.
A collect is an anonymous block.
-.IP @(and)
-Separator of clauses for @(some), @(all), @(none), @(maybe) and @(cases).
-Equivalent to @(or). Choice is stylistic.
-
-.IP @(or)
-Separator of clauses for @(some), @(all), @(none), @(maybe) and @(cases).
-Equivalent to @(and). Choice is stylistic.
-
-.IP @(end)
-Required terminator for @(some), @(all), @(none), @(maybe), @(cases), @(if),
-@(collect), @(coll), @(output), @(repeat), @(rep), @(try), @(block) and @(define).
-
-.IP @(fail)
+.coIP @(and)
+Separator of clauses for
+.codn @(some) ,
+.codn @(all) ,
+.codn @(none) ,
+.code @(maybe)
+and
+.codn @(cases) .
+Equivalent to
+.codn @(or) .
+The choice is stylistic.
+
+.coIP @(or)
+Separator of clauses for
+.codn @(some) ,
+.codn @(all) ,
+.codn @(none) ,
+.code @(maybe)
+and
+.codn @(cases) .
+Equivalent to
+.codn @(and) .
+The choice is stylistic.
+
+.coIP @(end)
+Required terminator for
+.codn @(some) ,
+.codn @(all) ,
+.codn @(none) ,
+.codn @(maybe) ,
+.codn @(cases) ,
+.codn @(if) ,
+.codn @(collect) ,
+.codn @(coll) ,
+.codn @(output) ,
+.codn @(repeat) ,
+.codn @(rep) ,
+.codn @(try) ,
+.code @(block)
+and
+.codn @(define) .
+
+.coIP @(fail)
Terminate the processing of a block, as if it were a failed match.
Blocks are discussed in the section BLOCKS below.
-.IP @(accept)
+.coIP @(accept)
Terminate the processing of a block, as if it were a successful match.
What bindings emerge may depend on the kind of block: collect
has special semantics. Blocks are discussed in the section BLOCKS below.
-.IP @(try)
+.coIP @(try)
Indicates the start of a try block, which is related to exception
handling, discussed in the EXCEPTIONS section below.
-.IP "@(catch), @(finally)"
-Special clauses within @(try). See EXCEPTIONS below.
+.ccIP @ @(catch) and @ @(finally)
+Special clauses within
+.codn @(try) .
+See EXCEPTIONS below.
-.IP "@(defex), @(throw)"
+.ccIP @ @(defex) and @ @(throw)
Define custom exception types; throw an exception. See EXCEPTIONS below.
-.IP @(assert)
+.coIP @(assert)
The assert directive requires the following material to match, otherwise
it throws an exception. It is useful for catching mistakes or omissions
in parts of a query that are sure-fire matches.
-.IP @(flatten)
+.coIP @(flatten)
Normalizes a set of specified variables to one-dimensional lists. Those
variables which have scalar value are reduced to lists of that value.
Those which are lists of lists (to an arbitrary level of nesting) are converted
to flat lists of their leaf values.
-.IP @(merge)
+.coIP @(merge)
Binds a new variable which is the result of merging two or more
other variables. Merging has somewhat complicated semantics.
-.IP @(cat)
+.coIP @(cat)
Decimates a list (any number of dimensions) to a string, by catenating its
constituent strings, with an optional separator string between all of the
values.
-.IP @(bind)
+.coIP @(bind)
Binds one or more variables against a value using a structural
pattern match. A limited form of unification takes place which can cause a
match to fail.
-.IP @(set)
+.coIP @(set)
Destructively assigns one or more existing variables using a structural
pattern, using syntax similar to bind. Assignment to unbound
variables triggers an error.
-.IP @(rebind)
+.coIP @(rebind)
Evaluates an expression in the current binding environment, and
then creates new bindings for the variables in the structural pattern.
Useful for temporarily overriding variable values in a scope.
-.IP @(forget)
+.coIP @(forget)
Removes variable bindings.
-.IP @(local)
-Synonym of @(forget).
+.coIP @(local)
+Synonym of
+.codn @(forget) .
-.IP @(output)
+.coIP @(output)
A directive which encloses an output clause in the query. An output section
does not match text, but produces text. The directives above are not
understood in an output clause.
-.IP @(repeat)
+.coIP @(repeat)
A directive understood within an @(output) section, for repeating multi-line
-text, with successive substitutions pulled from lists. The directive @(rep)
+text, with successive substitutions pulled from lists. The directive
+.code @(rep)
produces iteration over lists horizontally within one line.
-.IP @(deffilter)
+.coIP @(deffilter)
This directive is used for defining named filters, which are useful
for filtering variable substitutions in output blocks. Filters are useful
when data must be translated between different representations that
@@ -1597,143 +2787,240 @@ have different special characters or other syntax, requiring escaping
or similar treatment. Note that it is also possible to use a function
as a filter. See Function Filters below.
-.IP @(filter)
+.coIP @(filter)
The filter directive passes one or more variables through a given
filter or chain or filters, updating them with the filtered values.
-.IP @(load)
+.coIP @(load)
The load directive loads another TXR file and interprets its contents.
-.IP @(do)
+.coIP @(do)
The do directive is used to evaluate TXR Lisp expressions, discarding their
result values. See the TXR LISP section far below.
.PP
-.SH INPUT SCANNING AND DATA MANIPULATION
+.SH* INPUT SCANNING AND DATA MANIPULATION
-.SS The Next Directive
+.dir next
-The next directive indicates that the remainder of the query is to be applied
+The
+.code next
+directive indicates that the remainder of the query is to be applied
to a new input source.
It can only occur by itself as the only element in a query line,
and takes various arguments, according to these possibilities:
- @(next)
- @(next SOURCE)
- @(next SOURCE :nothrow)
- @(next :args)
- @(next :env)
- @(next :list EXPR)
- @(next :string EXPR)
-
-The lone @(next) without arguments switches to the next file in the
+.cblk
+.mets @(next)
+.mets @(next << source )
+.mets @(next < source :nothrow)
+.mets @(next :args)
+.mets @(next :env)
+.mets @(next :list << expr )
+.mets @(next :string << expr )
+.cble
+
+The lone
+.code @(next)
+without arguments switches to the next file in the
argument list which was passed to the
.B TXR
utility. However, "switch to the next file" means in a pattern matching
way, not in an imperative way. It is possible for the pattern matching
logic to implicitly backtrack to the previous file.
-If SOURCE is given, it must be text-valued expression which denotes an
+If
+.meta source
+is given, it must be text-valued expression which denotes an
input source; it may be a string literal, quasiliteral or a variable.
-For instance, if variable A contains the text "data", then
-
- @(next A)
-
-means switch to the file called "data", and
-
- @(next `@A.txt`)
-
-means to switch to the file "data.txt".
+For instance, if variable
+.code A
+contains the text
+.strn "data" ,
+then
+.code @(next A)
+means switch to the file called
+.strn "data" ,
+and
+.code @(next `@A.txt`)
+means to switch to the file
+.strn "data.txt" .
If the input source cannot be opened for whatever reason,
.B TXR
throws an exception (see EXCEPTIONS below). An unhandled exception will
terminate the program. Often, such a drastic measure is inconvenient;
-if @(next) is invoked with the :nothrow keyword, then if the input
+if
+.code @(next)
+is invoked with the
+.code :nothrow
+keyword, then if the input
source cannot be opened, the situation is treated as a simple
match failure.
-The variant @(next :args) means that the remaining command line arguments are to
+The variant
+.code @(next :args)
+means that the remaining command line arguments are to
be treated as a data source. For this purpose, each argument is considered to
be a line of text. If an argument is currently being processed as an input
source, that argument is included at the front of the list. As the arguments
-are matched, they are consumed. This means that if a @(next) directive without
-arguments is executed in the scope of @(next :args), it opens the file named
-by the first unconsumed argument.
+are matched, they are consumed. This means that if a
+.code @(next)
+directive without
+arguments is executed in the scope of
+.codn "@(next :args)" ,
+it opens the file named
+by the first unconsumed argument.
To process arguments, and then continue with the original file and argument
-list, wrap the argument processing in a @(block).
+list, wrap the argument processing in a
+.codn @(block) .
-The variant @(next :env) means that the list of process environment variables
+The variant
+.code @(next :env)
+means that the list of process environment variables
is treated as a source of data. It looks like a text file stream
-consisting of lines of the form "name=value". If this feature is not available
+consisting of lines of the form
+.strn "name=value" .
+If this feature is not available
on a given platform, an exception is thrown.
-The syntax @(next :list EXPR) treats the expression as a source of
+The syntax
+.cblk
+.meti @(next :list << expr)
+.cble
+treats the expression as a source of
text. The value of the expression is flattened to a list in a way similar
-to the @(flatten) directive. The resulting list is treated as if it were the
+to the
+.code @(flatten)
+directive. The resulting list is treated as if it were the
lines of a text file: each element of the list is a line. If the lines
happen contain embedded newline characters, they are a visible constituent
of the line, and do not act as line separators.
-The syntax @(next :string EXPR) treats the expression as a source of
+The syntax
+.cblk
+.meti @(next :string << expr)
+.cble
+treats the expression as a source of
text. The value of the expression must be a string. Newlines in the string are
-interpreted as line terminators.
+interpreted as line terminators.
A string which is not terminated by
a newline is tolerated, so that:
+.cblk
@(next :string "abc")
@a
+.cble
-binds a to "abc". Likewise, this is also the case with input files and other
+binds
+.code a
+to
+.strn "abc" .
+Likewise, this is also the case with input files and other
streams whose last line is not terminated by a newline.
However, watch out for empty strings, which are analogous to a correctly formed
empty file which contains no lines:
+.cblk
@(next :string "")
@a
-
-This will not bind a to ""; it is a matching failure. The behavior of :list is
+.cble
+
+This will not bind
+.code a
+to
+.strn "" ;
+it is a matching failure. The behavior of
+.code :list
+is
different. The query
+.cblk
@(next :list "")
@a
-
-binds a to "". The reason is that under :list the string "" is flattened to
-the list ("") which is not an empty input stream, but a stream consisting of
+.cble
+
+binds
+.code a
+to
+.strn "" .
+The reason is that under
+.code :list
+the string
+.str ""
+is flattened to
+the list
+.cblk
+("")
+.cble
+which is not an empty input stream, but a stream consisting of
one empty line.
Note that "remainder of the query" which is applied to the stream opened
-by @(next) refers to the subquery in which the next directive appears, not
+by
+.code @(next)
+refers to the subquery in which the next directive appears, not
necessarily the entire query. For example, the following query looks for the
-line starting with "xyz" at the top of the file "foo.txt", within a some
-directive. After the @(end) which terminates the @(some), the "abc" is matched
-in the previous file again.
-
+line starting with
+.str "xyz"
+at the top of the file
+.strn "foo.txt" ,
+within a some
+directive. After the
+.code @(end)
+which terminates the
+.codn @(some) ,
+the
+.str "abc"
+is matched in the previous file again.
+
+.cblk
@(some)
@(next "foo.txt")
xyz@suffix
@(end) abc
-
-However, if the @(some) subquery successfully matched "xyz@suffix" within the
-file foo.text, there is now a binding for the suffix variable, which
+.cble
+
+However, if the
+.code @(some)
+subquery successfully matched
+.str "xyz@suffix"
+within the
+file
+.codn foo.text ,
+there is now a binding for the suffix variable, which
is visible to the remainder of the entire query. The variable bindings
survive beyond the clause, but the data stream does not.
-The @(next) directive supports the file name conventions as the command
-line. The name - means standard input. Text which starts with a ! is
+The
+.code @(next)
+directive supports the file name conventions as the command
+line. The name
+.code -
+means standard input. Text which starts with a
+.code !
+is
interpreted as a shell command whose output is read like a file. These
interpretations are applied after variable substitution. If the file is
-specified as @a, but the variable a expands to "!echo foo", then the output of
-the "echo foo" command will be processed.
-
-.SS The Skip Directive
-
-The skip directive considers the remainder of the query as a search
+specified as
+.codn @a ,
+but the variable a expands to
+.strn "!echo foo" ,
+then the output of
+the
+.str "echo foo"
+command will be processed.
+
+.dir skip
+
+The
+.code skip
+directive considers the remainder of the query as a search
pattern. The remainder is no longer required to strictly match at the
current line in the current file. Rather, the current file is searched,
starting with the current line, for the first line where the entire remainder
@@ -1747,134 +3034,226 @@ Each such directive performs a recursive subsearch.
Skip comes in vertical and horizontal flavors. For instance, skip and match the
last line:
+.cblk
@(skip)
@last
@(eof)
+.cble
Skip and match the last character of the line:
+.cblk
@(skip)@{last 1}@(eol)
+.cble
The skip directive has two optional arguments. If the first argument is a
number, its value limits the range of lines scanned for a match. Judicious use
of this feature can improve the performance of queries.
-Example: scan until "size: @SIZE" matches, which must happen within
+Example: scan until
+.str "size: @SIZE"
+matches, which must happen within
the next 15 lines:
+.cblk
@(skip 15)
size: @SIZE
+.cble
Without the range limitation skip will keep searching until it consumes
the entire input source. While sometimes this is what is intended,
often it is not. Sometimes a skip is nested within a collect, or
following another skip. For instance, consider:
+.cblk
@(collect)
begin @BEG_SYMBOL
@(skip)
end @BEG_SYMBOL
@(end)
+.cble
The collect iterates over the entire input. But, potentially, so does
-the skip. Suppose that "begin x" is matched, but the data has no
-matching "end x". The skip will search in vain all the way to the end of the
+the skip. Suppose that
+.str "begin x"
+is matched, but the data has no
+matching
+.strn "end x" .
+The skip will search in vain all the way to the end of the
data, and then the collect will try another iteration back at the
beginning, just one line down from the original starting point. If it is a
-reasonable expectation that an "end x" occurs 15 lines of a "begin x", this can
-be written instead:
+reasonable expectation that an
+.code "end x"
+occurs 15 lines of a
+.strn "begin x" ,
+this can be written instead:
+.cblk
@(collect)
begin @BEG_SYMBOL
@(skip 15)
end @BEG_SYMBOL
@(end)
-
-If the symbol nil is used in place of a number, it means to scan
-an unlimited range of lines; thus, @(skip nil) is equivalent to @(skip).
-
-If the symbol :greedy is used, it changes the semantics of the skip
-to longest match semantics, like the regular expression * operator.
-For instance, match the last three space-separated tokens of the line:
-
+.cble
+
+If the symbol
+.code nil
+is used in place of a number, it means to scan
+an unlimited range of lines; thus,
+.code @(skip nil)
+is equivalent to
+.codn @(skip) .
+
+If the symbol
+.code :greedy
+is used, it changes the semantics of the skip
+to longest match semantics. For instance, match the last three space-separated
+tokens of the line:
+
+.cblk
@(skip :greedy) @a @b @c
-
-Without :greedy, the variable @c will can match multiple tokens,
-and end up with spaces in it, because nothing follows @c and
-so it matches from any position which follows a space to the
-end of the line. Also note the space in front of @a. Without this
-space, @a will get an empty string.
+.cble
+
+Without
+.codn :greedy ,
+the variable
+.code @c
+will can match multiple tokens,
+and end up with spaces in it, because nothing follows
+.code @c
+and so it matches from any position which follows a space to the
+end of the line. Also note the space in front of
+.codn @a .
+Without this
+space,
+.code @a
+will get an empty string.
A line oriented example of greedy skip: match the last line without
-using @eof:
+using
+.codn @eof :
+.cblk
@(skip :greedy)
@last_line
+.cble
There may be a second numeric argument. This specifies a minimum
number of lines to skip before looking for a match. For instance,
-skip 15 lines and then search indefinitely for "begin ...":
+skip 15 lines and then search indefinitely for
+.codn "begin ..." :
+.cblk
@(skip nil 15)
begin @BEG_SYMBOL
+.cble
The two arguments may be used together. For instance, the following
-matches if, and only if, the 15th line of input starts with "begin ":
+matches if, and only if, the 15th line of input starts with
+.codn "begin " :
+.cblk
@(skip 1 15)
begin @BEG_SYMBOL
-
-Essentially, @(skip 1 <n>) means "hard skip by <n>" lines, then
-match the query without scanning. @(skip 1 0) is the same as @(skip 1), which
-is a noop, because it means: "the remainder of the query must match starting on
-the very next line", or, more briefly, "skip exactly zero lines", which is the
-behavior if the skip directive is omitted altogether.
+.cble
+
+Essentially,
+.cblk
+.meti @(skip 1 << n )
+.cble
+means "hard skip by
+.meta n
+lines".
+.code @(skip 1 0)
+is the same as
+.codn "@(skip 1)" ,
+which is a noop, because it means: "the remainder of the query must match
+starting on the very next line", or, more briefly, "skip exactly zero lines",
+which is the behavior if the skip directive is omitted altogether.
Here is one trick for grabbing the fourth line from the bottom of the input:
+.cblk
@(skip)
@fourth_from_bottom
@(skip 1 3)
@(eof)
+.cble
Or using greedy skip:
+.cblk
@(skip :greedy)
@fourth_from_bottom
@(skip 1 3)
+.cble
-Nongreedy skip with the @(eof) has a slight advantage because the greedy skip
+Nongreedy skip with the
+.code @(eof)
+has a slight advantage because the greedy skip
will keep scanning even though it has found the correct match, then backtrack
to the last good match once it runs out of data. The regular skip with explicit
-@(eof) will stop when the @(eof) matches.
+.code @(eof)
+will stop when the
+.code @(eof)
+matches.
-.SS Reducing Backtracking with Blocks
+.SS* Reducing Backtracking with Blocks
-Skip can consume considerable CPU time when multiple skips are nested.
-Consider:
+.code skip
+can consume considerable CPU time when multiple skips are nested. Consider:
+.cblk
@(skip)
A
@(skip)
B
@(skip)
C
+.cble
This is actually nesting: the second a third skips occur within the body of the
first one, and thus this creates nested iteration. TXR is searching for the
-combination of skips which find match the pattern of lines A, B and C, with
+combination of skips which find match the pattern of lines
+.codn A ,
+.code B
+and
+.codn C ,
+with
backtracking behavior. The outermost skip marches through the data until it
-finds A, followed by a pattern match for the second skip. The second skip
-iterates within to find B, followed by the third skip, and the third skip
-iterates to find C. If there is only one line A, and one B, then this is
-reasonably fast. But suppose there are many lines matching A and B,
-giving rise to a large number combinations of skips which match A and B, and
-yet no match for C, triggering backtracking. The nested stepping which tries
-the combinations of A and B can give rise to a considerable running time.
+finds
+.codn A ,
+followed by a pattern match for the second skip. The second skip
+iterates within to find
+.codn B ,
+followed by the third skip, and the third skip
+iterates to find
+.codn C .
+If there is only one line
+.codn A ,
+and one
+.codn B ,
+then this is reasonably fast. But suppose there are many lines matching
+.code A
+and
+.codn B ,
+giving rise to a large number combinations of skips which match
+.code A
+and
+.codn B ,
+and yet no match for
+.codn C ,
+triggering backtracking. The nested stepping which tries
+the combinations of
+.code A
+and
+.code B
+can give rise to a considerable running time.
One way to deal with the problem is to unravel the nesting with the help of
blocks. For example:
+.cblk
@(block)
@ (skip)
A
@@ -1885,9 +3264,12 @@ blocks. For example:
@(end)
@(skip)
C
+.cble
Now the scope of each skip is just the remainder of the block in which it
-occurs. The first skip finds A, and then the block ends. Control passes to the
+occurs. The first skip finds
+.codn A ,
+and then the block ends. Control passes to the
next block, and backtracking will not take place to a block which completed
(unless all these blocks are enclosed in some larger construct which
backtracks, causing the blocks to be re-executed.
@@ -1895,6 +3277,7 @@ backtracks, causing the blocks to be re-executed.
Of course, this rewrite is not equivalent, and cannot be used for instance
in backreferencing situations such as:
+.cblk
@;
@; Find some three lines which are the same.
@;
@@ -1904,44 +3287,65 @@ in backreferencing situations such as:
@line
@(skip)
@line
+.cble
This example depends on the nested search-within-search semantics.
-.SS The Trailer Directive
+.dir trailer
-The trailer directive introduces a trailing portion of a query or subquery
+The
+.code trailer
+directive introduces a trailing portion of a query or subquery
which matches input material normally, but in the event of a successful match,
does not advance the current position. This can be used, for instance, to
-cause @(collect) to match partially overlapping regions.
+cause
+.code @(collect)
+to match partially overlapping regions.
Example:
+.cblk
@(collect)
@line
@(trailer)
@(skip)
@line
@(end)
+.cble
This script collects each line which has a duplicate somewhere later
-in the input. Without the @(trailer) directive, this does not work properly
+in the input. Without the
+.code @(trailer)
+directive, this does not work properly
for inputs like:
+.cblk
111
222
111
222
-
-Without @(trailer), the first duplicate pair constitutes a match which
-spans over the 222. After that pair is found, the matching continues
-after the second 111.
-
-With the @(trailer) directive in place, the collect body, on each
-iteration, only consumes the lines matched prior to @(trailer).
-
-.SS The Freeform Directive
-
-The freeform directive provides a useful alternative to
+.cble
+
+Without
+.codn @(trailer) ,
+the first duplicate pair constitutes a match which
+spans over the
+.codn 222 .
+After that pair is found, the matching continues
+after the second
+.codn 111 .
+
+With the
+.code @(trailer)
+directive in place, the collect body, on each
+iteration, only consumes the lines matched prior to
+.codn @(trailer) .
+
+.dir freeform
+
+The
+.code freeform
+directive provides a useful alternative to
.B TXR's
line-oriented matching discipline. The freeform directive treats all remaining
input from the current input source as one big line. The query line which
@@ -1949,30 +3353,38 @@ immediately follows freeform is applied to that line.
The syntax variations are:
+.cblk
@(freeform)
... query line ..
- @(freeform NUMBER)
+.mets @(freeform << number )
... query line ..
- @(freeform STRING)
+.mets @(freeform << string )
... query line ..
- @(freeform NUMBER STRING)
+.mets @(freeform < number << string )
... query line ..
+.cble
-The string and numeric arguments, if both are present, may be given in either
-order.
+If
+.meta number
+and
+.meta string
+are both present, they may be given in either order.
If a numeric argument is given, it limits the range of lines which are combined
-together. For instance @(freeform 5) means to only consider the next five lines
+together. For instance
+.code @(freeform 5)
+means to only consider the next five lines
to to be one big line. Without a numeric argument, freeform is "bottomless". It
can match the entire file, which creates the risk of allocating a large amount
of memory.
If a string argument is given, it specifies a custom line terminator. The
-default terminator is "\en". The terminator does not have to be one character
-long.
+default terminator is
+.strn "\en" .
+The terminator does not have to be one character long.
Freeform does not convert the entire remainder of the input into one big line
all at once, but does so in a dynamic, lazy fashion, which takes place as the
@@ -1984,80 +3396,133 @@ After the subquery is applied to the virtual line, the unmatched remainder
of that line is broken up into multiple lines again, by looking for and
removing all occurrences of the terminator string within the flattened portion.
-Care must be taken if the terminator is other than the default "\en". All
-occurrences of the terminator string are treated as line terminators in
+Care must be taken if the terminator is other than the default
+.strn "\en" .
+All occurrences of the terminator string are treated as line terminators in
the flattened portion of the data, so extra line breaks may be introduced.
Likewise, in the yet unflattened portion, no breaking takes place, even if
the text contains occurrences of the terminator string. The extent of data which
is flattened, and the amount of it which remains, depends entirely on the
-query line underneath @(flatten).
+query line underneath
+.codn @(flatten) .
In the following example, lines of data are flattened using $ as the line
terminator.
+.IP code:
+.cblk
+\ @(freeform "$")
+ @a$@b:
+ @c
+ @d
+.cble
+
+.IP data:
+.cblk
+\ 1
+ 2:3
+ 4
+.cble
+
+.IP "output (\f[4]-B\f[]):"
+.cblk
+\ a="1"
+ b="2"
+ c="3"
+ d="4"
+.cble
+.PP
- Query: @(freeform "$")
- @a$@b:
- @c
- @d
-
- Data: 1
- 2:3
- 4
-
- Output (-B): a="1"
- b="2"
- c="3"
- d="4"
-
-The data is turned into the virtual line 1$2:3$4$. The @a$@b: subquery matches
-the 1$2: portion, binding a to 1, and b to 2. The remaining portion 3$4$ is
-then split into separate lines again according to the line terminator $:
-
- 3
- 4
+The data is turned into the virtual line
+.codn 1$2:3$4$ .
+The
+.code @a$@b:
+subquery matches
+the
+.code 1$2:
+portion, binding
+.code a
+to
+.strn 1 ,
+and
+.code b
+to
+.strn 2 .
+The remaining portion
+.code 3$4$
+is then split into separate lines again according to the line terminator
+.codn $i :
+
+.cblk
+ 3
+ 4
+.cble
Thus the remainder of the query
- @c
- @d
-
-faces these lines, binding c to 3 and d to 4. Note that since the data
+.cblk
+ @c
+ @d
+.cble
+
+faces these lines, binding
+.code c
+to
+.code 3
+and
+.code d
+to
+.codn 4 .
+Note that since the data
does not contain dollar signs, there is no ambiguity; the meaning may be
understood in terms of the entire data being flattened and split again.
-In the following example, freeform is used to solve a tokenizing problem. The
+In the following example,
+.code freeform
+is used to solve a tokenizing problem. The
Unix password file has fields separated by colons. Some fields may be empty.
-Using freeform, we can join the password file using ":" as a terminator.
+Using freeform, we can join the password file using
+.str ":"
+as a terminator.
By restricting freeform to one line, we can obtain each line of the password
-file with a terminating ":", allowing for a simple tokenization, because
+file with a terminating
+.strn ":" ,
+allowing for a simple tokenization, because
now the fields are colon-terminated rather than colon-separated.
Example:
+.cblk
@(next "/etc/passwd")
@(collect)
@(freeform 1 ":")
@(coll)@{token /[^:]*/}:@(end)
@(end)
+.cble
-.SS The Fuzz Directive
+.dir fuzz
-The fuzz directive allows for an imperfect match spanning a set number of
+The
+.code fuzz
+directive allows for an imperfect match spanning a set number of
lines. It takes two arguments, both expressions that should evaluate
to integers:
+.cblk
@(fuzz m n)
...
+.cble
This expresses that over the next n query lines, the matching strictness
is relaxed a little bit. Only m out of those n lines have to match.
Afterward, the rest of the query follows normal, strict processing.
In the degenerate situation that there are fewer than n query lines following
-the fuzz directive, then m of them must succeed nevertheless. (If there
+the
+.code fuzz
+directive, then m of them must succeed nevertheless. (If there
are fewer than m, then this is impossible.)
-.SS The Some, All, None, Maybe, Cases and Choose directives
+.dirs some all none maybe cases choose
These directives, called the parallel directives, combine multiple subqueries,
which are applied at the same input position, rather than to consecutive input.
@@ -2072,6 +3537,7 @@ position by some whole number of lines.
The syntax of these parallel directives follows this example:
+.cblk
@(some)
subquery1
.
@@ -2088,33 +3554,54 @@ The syntax of these parallel directives follows this example:
.
.
@(end)
+.cble
And in horizontal mode:
+.cblk
@(some)subquery1...@(and)subquery2...@(and)subquery3...@(end)
+.cble
Long horizontal lines can be broken up with line continuations, allowing the
above example to be written like this, which is considered a single logical
line:
- @(some)@\
- subquery1...@\
- @(and)@\
- subquery2...@\
- @(and)@\
- subquery3...@\
+.cblk
+ @(some)@\e
+ subquery1...@\e
+ @(and)@\e
+ subquery2...@\e
+ @(and)@\e
+ subquery3...@\e
@(end)
-
-The @(some), @(all), @(none), @(maybe), @(cases) or @(choose) must be followed
-by at least one subquery clause, and be terminated by @(end). If there are two
-or more subqueries, these additional clauses are indicated by @(and) or @(or),
+.cble
+
+The
+.codn @(some) ,
+.codn @(all) ,
+.codn @(none) ,
+.codn @(maybe) ,
+.code @(cases)
+or
+.code @(choose)
+must be followed
+by at least one subquery clause, and be terminated by
+.codn @(end) .
+If there are two
+or more subqueries, these additional clauses are indicated by
+.code @(and)
+or
+.codn @(or) ,
which are interchangeable. The separator and terminator directives also must
appear as the only element in a query line.
-The choose directive requires keyword arguments. See below.
+The
+.code choose
+directive requires keyword arguments. See below.
The syntax supports arbitrary nesting. For example:
+.cblk
QUERY: SYNTAX TREE:
@(all) all -+
@@ -2128,16 +3615,31 @@ The syntax supports arbitrary nesting. For example:
@ (end) | | +- end
a dark | +- TEXT
@(end) *- end
-
-nesting can be indicated using whitespace between @ and the
-directive expression. Thus, the above is an @(all) query containing a @(skip)
-clause which applies to a @(some) that is followed by the text line "a dark".
-The @(some) clause combines the text line "it", and a @(none) clause which
-contains just one clause consisting of the line "was".
+.cble
+
+nesting can be indicated using whitespace between
+.code @
+and the
+directive expression. Thus, the above is an
+.code @(all)
+query containing a
+.code @(skip)
+clause which applies to a
+.code @(some)
+that is followed by the text line
+.strn "a dark" .
+The
+.code @(some)
+clause combines the text line
+.strn it ,
+and a
+.code @(none)
+clause which contains just one clause consisting of the line
+.strn was .
The semantics of the parallel directives is:
-.IP @(all)
+.coIP @(all)
Each of the clauses is matched at the current position. If any of the
clauses fails to match, the directive fails (and thus does not produce
any variable bindings). Clauses following the failed directive are not
@@ -2145,27 +3647,36 @@ evaluated. Bindings extracted by a successful clause are visible to the clauses
which follow, and if the directive succeeds, all of the combined bindings
emerge.
-.IP "@(some [ :resolve (vars ...) ])"
+.meIP @(some [ :resolve >> ( var ...) ])
Each of the clauses is matched at the current position. If any of the clauses
succeed, the directive succeeds, retaining the bindings accumulated by the
successfully matching clauses. Evaluation does not stop on the first successful
clause. Bindings extracted by a successful clause are visible to the clauses
which follow.
-The :resolve parameter is for situations when the @(some) directive has
+The
+.code :resolve
+parameter is for situations when the
+.code @(some)
+directive has
multiple clauses that need to bind some common variables to different
values: for instance, output parameters in functions. Resolve takes
a list of variable name symbols as an argument. This is called the
-resolve set. If the clauses of @(some) bind variables in the resolve
+resolve set. If the clauses of
+.code @(some)
+bind variables in the resolve
set, those bindings are not visible to later clauses. However, those
-bindings do emerge out of the @(some) directive as a whole.
+bindings do emerge out of the
+.code @(some)
+directive as a whole.
This creates a conflict: what if two or more clauses introduce
-non-matching bindings for a variable in the resolve set?
+different bindings for a variable in the resolve set?
This is why it is called the resolve set: conflicts for variables in the
resolve set are automatically resolved in favor of later directives.
Example:
+.cblk
@(some :resolve (x))
@ (bind a "a")
@ (bind x "x1")
@@ -2173,33 +3684,50 @@ Example:
@ (bind b "b")
@ (bind x "x2")
@(end)
-
-Here, the two clauses both introduce a binding for x. Without the :resolve
-parameter, this would mean that the second clause fails, because x comes in
-with the value "x1", which does not bind with "x2". But because x is placed
-into the resolve set, the second clause does not see the "x1" binding. Both
-clauses establish their bindings independently creating a conflict over x.
+.cble
+
+Here, the two clauses both introduce a binding for
+.codn x .
+Without the
+.code :resolve
+parameter, this would mean that the second clause fails, because
+.code x
+comes in
+with the value
+.strn x1 ,
+which does not bind with
+.strn x2 .
+But because
+.code x
+is placed
+into the resolve set, the second clause does not see the
+.str x1
+binding. Both
+clauses establish their bindings independently creating a conflict over
+.codn x .
The conflict is resolved in favor of the second clause, and so the bindings
which emerge from the directive are:
+.cblk
a="a"
b="b"
x="x2"
+.cble
-.IP @(none)
+.coIP @(none)
Each of the clauses is matched at the current position. The
directive succeeds only if all of the clauses fail. If
any clause succeeds, the directive fails, and subsequent clauses are not
evaluated. Thus, this directive never produces variable bindings, only matching
success or failure.
-.IP @(maybe)
+.coIP @(maybe)
Each of the clauses is matched at the current position. The directive always
succeeds, even if all of the clauses fail. Whatever bindings are found in any
of the clauses are retained. Bindings extracted by any successful clause are
visible to the clauses which follow.
-.IP @(cases)
+.coIP @(cases)
Each of the clauses is matched at the current position.
The clauses are matched, in order, at the current position.
If any clause matches, the matching stops and the bindings
@@ -2207,16 +3735,21 @@ collected from that clause are retained. Any remaining clauses
after that one are not processed. If no clause matches, the
directive fails, and produces no bindings.
-.IP "@(choose [ :longest <var> | :shortest <var> ])"
+.meIP @(choose [ :longest < var | :shortest < var ])
Each of the clauses is matched at the current position in order. In this
construct, bindings established by an earlier clause are not visible to later
clauses. Although any or all of the clauses can potentially match, the clause
which succeeds is the one which maximizes or minimizes the length of the
text bound to the specified variable. The other clauses have no effect.
-For all of the parallel directives other than @(none) and @(choose), the query
+For all of the parallel directives other than
+.code @(none)
+and
+.codn @(choose) ,
+the query
advances the input position by the greatest number of lines that match in any
-of the successfully matching subclauses that are evaluated. The @(none)
+of the successfully matching subclauses that are evaluated. The
+.code @(none)
directive does not advance the input position.
For instance if there are two subclauses, and one of them matches three lines,
@@ -2224,39 +3757,51 @@ but the other one matches five lines, then the overall clause is considered to
have made a five line match at its position. If more directives follow, they
begin matching five lines down from that position.
-.SS The Require Directive
+.dir require
-The syntax of @(require) is:
+The syntax of
+.code @(require)
+is:
- @(require <lisp-expression>)
+.cblk
+.mets @(require << lisp-expression )
+.cble
The require directive evaluates a TXR Lisp expression. (See TXR LISP far
below.) If the expression yields a true value, then it succeeds, and matching
continues with the directives which follow. Otherwise the directive fails.
-In the context of the @(require) directive, should not be delimited by an @.
+In the context of the
+.code require
+directive, the expression should not be introduced by the
+.code @
+symbol; it is expected to be a Lisp expression.
Example:
- @# require that 4 is greater than 3
- @# This succeeds; therefore, @a is processed
+.cblk
+ @; require that 4 is greater than 3
+ @; This succeeds; therefore, @a is processed
@(require (> (+ 2 2) 3))
@a
+.cble
+.dir if
-.SS The If Directive
-
-The syntax of the directive can be exemplified as follows
+The syntax of the
+.code if
+directive can be exemplified as follows:
- @(if <lisp-expr>)
+.cblk
+.mets @(if << lisp-expr )
.
.
.
- @(elif <lisp-expr>)
+.mets @(elif << lisp-expr )
.
.
.
- @(elif <lisp-expr>)
+.mets @(elif << lisp-expr )
.
.
.
@@ -2265,62 +3810,99 @@ The syntax of the directive can be exemplified as follows
.
.
@(end)
-
-The @(elif) and @(else) clauses are all optional. If @(else) is present, it must be
-last, before @(end), after any @(elif) clauses. Any of the clauses may be empty.
+.cble
+
+The
+.code @(elif)
+and
+.code @(else)
+clauses are all optional. If
+.code @(else)
+is present, it must be
+last, before
+.codn @(end) ,
+after any
+.code @(elif)
+clauses. Any of the clauses may be empty.
See the TXR Lisp section about TXR Lisp expressions. In this directive, TXR Lisp
-expressions are not introduced by the @ symbol.
+expressions are not introduced by the
+.code @
+symbol, just like in the
+.code require
+directive.
For example:
+.cblk
@(if (> (length str) 42))
foo: @a @b
@(else)
{@c}
@(end)
-
-In this example, if the length of the variable str is greater than 42, then
-matching continues with "foo: @a b", otherwise it proceeds with {@c}.
-
-The if directive is actually a syntactic sugar which is translated to @(cases)
-and @(require). That is to say, the following pattern:
-
+.cble
+
+In this example, if the length of the variable
+.code str
+is greater than
+.codn 42 ,
+then matching continues with
+.strn "foo: @a b" ,
+otherwise it proceeds with
+.codn {@c} .
+
+The
+.code if
+directive is actually a syntactic sugar which is translated to
+.code @(cases)
+and
+.codn @(require) .
+That is to say, the following pattern:
+
+.cblk
@(cases)
- @(require <lisp-expr-1>)
+.mets @(require << lisp-expr-1 )
A
@(or)
- @(require <lisp-expr-2>)
+.mets @(require << lisp-expr-2 )
B
@(or)
C
@(end)
+.cble
corresponds to the somewhat shorter and clearer:
- @(if <lisp-expr-1>)
+.cblk
+.mets @(if << lisp-expr-1 )
A
- @(elsif <lisp-expr-2>)
+.mets @(elsif << lisp-expr-2 )
B
@(else)
C
@(end)
+.cble
-.SS The Gather Directive
+.dir gather
Sometimes text is structured as items that can appear in an arbitrary order.
When multiple matches need to be extracted, there is a combinatorial explosion
of possible orders, making it impractical to write pattern matches for all
the possible orders.
-The gather directive is for these situations. It specifies multiple clauses
+The
+.code gather
+directive is for these situations. It specifies multiple clauses
which all have to match somewhere in the data, but in any order.
-For further convenience, the lines of the first clause of the gather directive
+For further convenience, the lines of the first clause of the
+.code gather
+directive
are implicitly treated as separate clauses.
The syntax follows this pattern
+.cblk
@(gather)
one-line-query1
one-line-query2
@@ -2343,17 +3925,29 @@ The syntax follows this pattern
.
.
@(end)
+.cble
-Of course the multi-line clauses are optional. The gather directive takes
+Of course the multi-line clauses are optional. The
+.code gather
+directive takes
keyword parameters, see below.
-Similarly to @(collect), @(gather) has an optional until/last clause:
+.coNP The @ until / @ last clause in @ gather
+Similarly to
+.codn collect ,
+.code gather
+has an optional
+.cod3 until / last
+clause:
+
+.cblk
@(gather)
...
@(until)
...
@(end)
+.cble
How gather works is that the text is searched for matches for the single line
and multi-line queries. The clauses are applied in the order in which they appear.
@@ -2368,36 +3962,61 @@ directive fails.
Example: extract several environment variables, which do not appear in a particular
order:
+.cblk
@(next :env)
@(gather)
USER=@USER
HOME=@HOME
SHELL=@SHELL
@(end)
+.cble
If the until or last clause is present and a match occurs, then the matches
from the other clauses are discarded and the gather terminates. The difference
-between until and last is that any bindings bindings established in last are
+between
+.cod3 until / last
+is that any bindings bindings established in last are
retained, and the input position is advanced past the matched material.
-The until/last clause has visibility to bindings established in the
+The
+.cod3 until / last
+clause has visibility to bindings established in the
previous clauses in that same iteration, even though those bindings
end up thrown away.
-.SS Gather Keyword Parameters
-
-The gather directive accepts the keyword parameter :vars. The argument to vars is
+.coNP Keyword parameters in @ gather
+The
+.code gather
+directive accepts the keyword parameter
+.codn :vars .
+The argument to vars is
a list of required and optional variables. Optional variables are denoted by
the specification of a default value. Example:
+.cblk
@(gather :vars (a b c (d "foo")))
...
@(end)
-
-Here, a, b, c and e are required variables, and d is optional. Variable e is
-required because its default value is the empty list (), same as the symbol
-nil.
-
-The presence of vars changes the behavior in three ways.
+.cble
+
+Here,
+.codn a ,
+.codn b ,
+.code c
+and
+.code e
+are required variables, and
+.code d
+is optional. Variable
+.code e
+is
+required because its default value is the empty list
+.codn () ,
+same as the symbol
+.codn nil .
+
+The presence of
+.code :vars
+changes the behavior in three ways.
Firstly, even if all the clauses in the gather match successfully and are
eliminated, the directive will fail if the required variables do not have
@@ -2406,22 +4025,31 @@ are established by the gather.
Secondly, if some of the clauses of the gather did not match, but all
of the required variables have bindings, then the directive succeeds.
-Without the presence of :vars, it would fail in this situation.
+Without the presence of
+.codn :vars ,
+it would fail in this situation.
-Thirdly, if the gather succeeds (all required variables have bindings),
+Thirdly, if
+.code gather
+succeeds (all required variables have bindings),
then all of the optional variables which do not have bindings are given
bindings to their default values.
-.SS The Collect Directive
+.dir collect
-The syntax of the collect directive is:
+The syntax of the
+.code collect
+directive is:
+.cblk
@(collect)
... lines of subquery
@(end)
+.cble
or with an until or last clause:
+.cblk
@(collect)
... lines of subquery: main clause
@(until)
@@ -2433,38 +4061,60 @@ or with an until or last clause:
@(last)
... lines of subquery: last clause
@(end)
+.cble
-The repeat symbol may be specified instead of collect, which changes
-the meaning, see below:
+The
+.code repeat
+symbol may be specified instead of
+.codn collect ,
+which changes the meaning, see below:
+.cblk
@(repeat)
... lines of subquery
@(end)
+.cble
The subquery is matched repeatedly, starting at the current line.
If it fails to match, it is tried starting at the subsequent line.
If it matches successfully, it is tried at the line following the
entire extent of matched data, if there is one. Thus, the collected regions do
not overlap. (Overlapping behavior can be obtained: see the
-@(trailer) directive).
-
-Unless certain keywords are specified, or unless the collect is explicitly
-failed with @(fail), it always succeeds, even if it collects nothing,
-and even if the until/last clause never finds a match.
-
-If no until/last clause is specified, and the collect is not limited
-using parameters, the collect is unbounded. It consumes the entire data
-file. If any query material follows such the collect clause, it will fail if it
+.code @(trailer)
+directive).
+
+Unless certain keywords are specified, or unless the collection is explicitly
+failed with
+.codn @(fail) ,
+it always succeeds, even if it collects nothing,
+and even if the
+.cod3 until / last
+clause never finds a match.
+
+If no
+.cod3 until / last
+last clause is specified, and the collect is not limited
+using parameters, the collection is unbounded: it consumes the entire data
+file. If any query material follows such the
+.code collect
+clause, it will fail if it
tries to match anything in the current file; but of course, it is possible to
-continue matching in another file by means of @(next).
+continue matching in another file by means of
+.codn @(next) .
-If an until/last clause is specified, the collection stops when that clause
-matches at the current position.
+.coNP The @ until / @ last clause in @ collect
-If an until clause terminates collect, no bindings are collected at that
+If an
+.cod3 until / last
+last clause is specified, the collection stops when that clause
+matches at the current position.
+
+If an
+.code until
+clause terminates collect, no bindings are collected at that
position, even if the main clause matches at that position also. Moreover, the
position is not advanced. The remainder of the query begins matching at that
-position.
+position.
If a last clause terminates collect, the behavior is different. Any bindings
captured by the main clause are thrown away, just like with the until clause.
@@ -2472,94 +4122,144 @@ However, the bindings in the last clause itself survive, and the position is
advanced to skip over that material.
Example:
+.IP code:
+.cblk
+\ @(collect)
+ @a
+ @(until)
+ 42
+ @b
+ @(end)
+ @c
+.cble
+.IP data:
+.cblk
+\ 1
+ 2
+ 3
+ 42
+ 5
+ 6
+.cble
+.IP result:
+.cblk
+\ a[0]="1"
+ a[1]="2"
+ a[2]="3"
+ c="42"
+.cble
+.PP
+
+The line
+.code 42
+is not collected, even though it matches
+.con @a .
+Furthermore,
+the
+.code @(until)
+does not advance the position, so variable
+.code c
+takes
+.codn 42 .
+
+If the
+.code @(until)
+is changed to
+.code @(last)
+the output will be different:
+.IP result:
+.cblk
+\ a[0]="1"
+ a[1]="2"
+ a[2]="3"
+ b="5"
+ c="6"
+.cble
+.PP
- Query: @(collect)
- @a
- @(until)
- 42
- @b
- @(end)
- @c
-
- Data: 1
- 2
- 3
- 42
- 5
- 6
-
- Output (-B): a[0]="1"
- a[1]="2"
- a[2]="3"
- c="42"
-
-The line 42 is not collected, even though it matches @a. Furthermore,
-the until does not advance the position, so variable c takes 42.
-
-If the @(until) is changed to @(last) the output will be different:
-
- Output (-B): a[0]="1"
- a[1]="2"
- a[2]="3"
- b=5
- c=6
-
-The 42 is not collected into the a list, just like before. But now
-the binding captured by @b emerges. Furthermore, the position advances
-so variable now takes 6.
+The
+.code 42
+is not collected into the a list, just like before. But now
+the binding captured by
+.code @b
+emerges. Furthermore, the position advances
+so variable now takes
+.codn 6 .
The binding variables within the clause of a collect are treated specially.
The multiple matches for each variable are collected into lists,
which then appear as array variables in the final output.
Example:
-
- Query: @(collect)
- @a:@b:@c
- @(end)
-
- Data: John:Doe:101
- Mary:Jane:202
- Bob:Coder:313
-
- Output (-B):
- a[0]="John"
- a[1]="Mary"
- a[2]="Bob"
- b[0]="Doe"
- b[1]="Jane"
- b[2]="Coder"
- c[0]="101"
- c[1]="202"
- c[2]="313"
+.IP code:
+.cblk
+\ @(collect)
+ @a:@b:@c
+ @(end)
+.cble
+.IP data:
+.cblk
+\ John:Doe:101
+ Mary:Jane:202
+ Bob:Coder:313
+.cble
+.IP result:
+.cblk
+\ a[0]="John"
+ a[1]="Mary"
+ a[2]="Bob"
+ b[0]="Doe"
+ b[1]="Jane"
+ b[2]="Coder"
+ c[0]="101"
+ c[1]="202"
+ c[2]="313"
+.cble
+.PP
The query matches the data in three places, so each variable becomes
a list of three elements, reported as an array.
Variables with list bindings may be referenced in a query. They denote a
-multiple match. The -D command line option can establish a one-dimensional
+multiple match. The
+.code -D
+command line option can establish a one-dimensional
list binding.
-Collect clauses may be nested. Variable matches collated into lists in an
+The clauses of
+.code collect
+may be nested. Variable matches collated into lists in an
inner collect, are again collated into nested lists in the outer collect.
-Thus an unbound variable wrapped in N nestings of @(collect) will
+Thus an unbound variable wrapped in N nestings of
+.code @(collect)
+will
be an N-dimensional list. A one dimensional list is a list of strings;
a two dimensional list is a list of lists of strings, etc.
It is important to note that the variables which are bound within the main
-clause of a collect - i.e. the variables which are subject to
-collection - appear, within the collect, as normal one-value bindings. The
+clause of a collect. That is, the variables which are subject to
+collection appear, within the collect, as normal one-value bindings. The
collation into lists happens outside of the collect. So for instance in the
query:
+.cblk
@(collect)
@x=@x
@(end)
-
-The left @x establishes a binding for some material preceding an equal sign.
-The right @x refers to that binding. The value of @x is different in each
+.cble
+
+The left
+.code @x
+establishes a binding for some material preceding an equal sign.
+The right
+.code @x
+refers to that binding. The value of
+.cod @x
+is different in each
iteration, and these values are collected. What finally comes out of the
-collect clause is list variable called x which holds each value that
+collect clause is a single variable called
+.code x
+which holds a list containing each value that
was ever instantiated under that name within the collect clause.
Also note that the until clause has visibility over the bindings
@@ -2567,173 +4267,317 @@ established in the main clause. This is true even in the terminating
case when the until clause matches, and the bindings of the main clause
are discarded.
-.SS Collect Keyword Parameters
-
-By default, collect searches the rest of the input indefinitely,
-or until the @(until) clause matches. It skips arbitrary amounts of
+.coNP Keyword Parameters in @ collect
+By default,
+.code collect
+searches the rest of the input indefinitely,
+or until the
+.cod3 until / last
+clause matches. It skips arbitrary amounts of
nonmatching material before the first match, and between matches.
-Within the @(collect) syntax, it is possible to specify some useful keyword
+Within the
+.code @(collect)
+syntax, it is possible to specify some useful keyword
parameters for additional control of the behavior. For instance
+.cblk
@(collect :maxgap 5)
+.cble
means that the collect will terminate if it does not find a match within five
lines of the starting position, or if more than five lines are skipped since
-any successful match. A :maxgap of 0 means that the collected regions must be
+any successful match. A
+.code :maxgap
+of
+.code 0
+means that the collected regions must be
adjacent. For instance:
+.cblk
@(collect :maxgap 0)
M @a
@(end)
+.cble
-means: from here, collect consecutive lines of the form "M ...". This will not
+means: from here, collect consecutive lines of the form
+.strn "M ..." .
+This will not
search for the first such line, nor will it skip lines which do not match this
form.
-Other keywords are :mingap, and :gap. The :mingap keyword specifies a minimum
+Other keywords are
+.codn :mingap ,
+and
+.codn :gap .
+The
+.code :mingap
+keyword specifies a minimum
gap between matches, but has no effect on the distance to the first match. The
-:gap keyword specifies :mingap and :maxgap at the same time, and can only be
+.code :gap
+keyword effectively specifies
+.code :mingap
+and
+.code :maxgap
+at the same time, and can only be
used if these other two are not used. Thus:
- @(collect :gap 1)
- @a
- @(end)
+.cblk
+ @(collect :gap 1)
+ @a
+ @(end)
+.cble
means collect every other line starting with the current line. Several
-other supported keywords are :times, :mintimes, :maxtimes and :lines.
-The shorthand :times N means the same thing as :mintimes N :maxtimes N.
+other supported keywords are
+.codn :times ,
+.codn :mintimes ,
+.code :maxtimes
+and
+.codn :lines .
+The shorthand
+.code :times N
+means the same thing as
+.codn ":mintimes N :maxtimes N" .
These specify how many matches should be collected. If there are fewer
-than mintimes matches, the collect fails. If maxtimes matches are collected,
+than
+.code :mintimes
+matches, the collect fails. If
+.code :maxtimes
+matches are collected,
collect stops collecting immediately. Example:
- @(collect :times 3)
- @a @b
- @(end)
+.cblk
+ @(collect :times 3)
+ @a @b
+ @(end)
+.cble
-This will collect a match for "@a @b" exactly three times. If three
+This will collect a match for
+.str @a @b
+exactly three times. If three
matches are not found, it will fail.
-The :lines parameter specifies the upper bound on how many lines
+The
+.code :lines
+parameter specifies the upper bound on how many lines
should be scanned by collect, measuring from the starting position.
The extent of the collect body is not counted. Example:
- @(collect :lines 2)
- foo: @a
- bar: @b
- baz: @c
- @(end)
+.cblk
+ @(collect :lines 2)
+ foo: @a
+ bar: @b
+ baz: @c
+ @(end)
+.cble
-The above collect will look for a match only twice: at the current position,
+The above
+.code collect
+will look for a match only twice: at the current position,
and one line down.
-There is one more keyword, :vars, discussed in the following section.
-
-.SS Specifying Variables in Collect
-
-Normally, any variable for which a new binding occurs in a collect is
-collected. A collect clause may be sloppy: it can neglect to collect some
-variables on some iterations, or bind some variables which are intended
-to behave like local temporaries, but end up collated into lists. Another issue
-is that the collect clause might not match anything at all, and then none of
-the variables are bound.
-
-The :vars keyword allows the query writer to add discipline the collect body.
-
-The argument to :vars is a list of variable specs. A variable spec is either a
-symbol, or a (<symbol> <expression>) pair, where the expression specifies a
+There is one more keyword,
+.codn :vars ,
+discussed in the following section.
+
+.coNP Specifying Variables in @ collect
+Normally, any variable for which a new binding occurs in a
+.code collect
+block is collected. A collect clause may be "sloppy": it can neglect to collect
+some variables on some iterations, or bind some variables which are intended to
+behave like local temporaries, but end up collated into lists. Another issue is
+that the collect clause might not match anything at all, and then none of the
+variables are bound.
+
+The
+.code :vars
+keyword allows the query writer to add discipline the
+.code collect
+body.
+
+The argument to
+.code :vars
+is a list of variable specs. A variable spec is either a
+symbol, or a
+.cblk
+.meti >> ( symbol << expression )
+.cble
+pair, where the expression specifies a
default value.
-When a :vars list is specified, it means that only the given variables can
+When a
+.code :vars
+list is specified, it means that only the given variables can
emerge from the successful collect. Any newly introduced bindings for other
variables do not propagate.
Furthermore, for any variable which is not specified with a default value, the
collect body, whenever it matches successfully, must bind that variable. If it
neglects to bind the variable, an exception of type query-error is thrown.
-(If a collect body matches successfully, but produces no new bindings, then
+(If a
+.code collect
+body matches successfully, but produces no new bindings, then
this error is suppressed.)
-For any variable which does have a default value, if the collect body neglects
-to bind that variable, the behavior is as if the collect did bind that variable
+For any variable which does have a default value, if the
+.code collect
+body neglects
+to bind that variable, the behavior is as if
+.code collect
+did bind that variable
to that default value.
The default values are expressions, and so can be quasiliterals.
-Lastly, if in the event that the collect does not match anything, the variables
+Lastly, if in the event that
+.code collect
+does not match anything, the variables
specified in vars (whether or not they have a default value) are all bound to
empty lists. (These bindings are established after the processing of the
-until/last clause, if present.)
+.cod3 until / last
+last clause, if present.)
Example:
+.cblk
@(collect :vars (a b (c "foo")))
@a @c
@(end)
+.cble
-Here, if the body "@a @c" matches, an error will be thrown because one of the
-mandatory variables is b, and the body neglects to produce a binding for b.
+Here, if the body
+.str @a @c
+matches, an error will be thrown because one of the
+mandatory variables is
+.codn b ,
+and the body neglects to produce a binding for
+.codn b .
Example:
+.cblk
@(collect :vars (a (c "foo")))
@a @b
@(end)
-
-Here, if "@a @b" matches, only a will be collected, but not b, because b is not
-in the variable list. Furthermore, because there is no binding for c in the
-body, a binding is created with the value "foo", exactly as if c matched
+.cble
+
+Here, if
+.str @a @b
+matches, only
+.code a
+will be collected, but not
+.codn b ,
+because
+.code b
+is not
+in the variable list. Furthermore, because there is no binding for
+.code c
+in the
+body, a binding is created with the value
+.strn foo ,
+exactly as if
+.code c
+matched
such a piece of text.
-In the following example, the assumption is that THIS NEVER MATCHES
-is not found anywhere in the input but the line THIS DOES MATCH is
-found and has a successor which is bound to a. Because the body did not
-match, the :vars a and b should be bound to empty lists. But a is bound
-by the last clause to some text, so this takes precedence. Only b is bound to a
-an empty list.
-
+In the following example, the assumption is that
+.code THIS NEVER MATCHES
+is not found anywhere in the input but the line
+.code THIS DOES MATCH
+is found and has a successor which is bound to
+.codn a .
+Because the body did not
+match, the
+.code :vars
+.code a
+and
+.cod b
+should be bound to empty lists. But
+.code a
+is bound by the last clause to some text, so this takes precedence. Only
+.code b
+is bound to an empty list.
+
+.cblk
@(collect :vars (a b))
THIS NEVER MATCHES
@(last)
THIS DOES MATCH
@a
@(end)
+.cble
The following means: do not allow any variables to propagate out of any
iteration of the collect and therefore collect nothing:
+.cblk
@(collect :vars nil)
...
@(end)
-
-Instead of writing @(collect :vars nil), it is possible to write
-@(repeat). @(repeat) takes all collect keywords, except for :vars.
-There is a repeat directive used in @(output) clauses; that is
-a different repeat directive.
-
-.SS The Coll Directive
-
-The coll directive is a kind of miniature version of the collect directive.
-Whereas the collect directive works with multi-line clauses on line-oriented
-material, coll works within a single line. With coll, it is possible to
+.cble
+
+Instead of writing
+.codn "@(collect :vars nil)" ,
+it is possible to write
+.codn @(repeat) .
+.code @(repeat)
+takes all collect keywords, except for
+.codn :vars .
+There is a
+.code @(repeat)
+directive used in
+.code @(output)
+clauses; that is a different directive.
+
+.dir coll
+
+The
+.code coll
+directive is the horizontal version of
+.codn collect .
+Whereas
+.code collect
+works with multi-line clauses on line-oriented
+material,
+.code coll
+works within a single line. With
+.codn coll ,
+it is possible to
recognize repeating regularities within a line and collect lists.
Regular-expression based Positive Match variables work well with coll.
Example: collect a comma-separated list, terminated by a space.
+.IP code:
+.cblk
+\ @(coll)@{A /[^, ]+/}@(until) @(end)@B
+.cble
+.IP data:
+.cblk
+\ foo,bar,xyzzy blorch
+.cble
+.IP result:
+.cblk
+\ A[0]="foo"
+ A[1]="bar"
+ A[2]="xyzzy"
+ B=blorch
+.cble
+.PP
- pattern: @(coll)@{A /[^, ]+/}@(until) @(end)@B
- data: foo,bar,xyzzy blorch
- result: A[0]="foo"
- A[1]="bar"
- A[2]="xyzzy"
- B=blorch
-
-Here, the variable A is bound to tokens which match the regular
-expression /[^, ]+/: non-empty sequence of characters other than commas or
+Here, the variable
+.code A
+is bound to tokens which match the regular
+expression
+.code /[^, ]+/:
+non-empty sequence of characters other than commas or
spaces.
-Like its big cousin, the coll directive searches for matches. If no match
+Like
+.codn collect ,
+.code coll
+searches for matches. If no match
occurs at the current character position, it tries at the next character
position. Whenever a match occurs, it continues at the character position which
follows the last character of the match, if such a position exists.
@@ -2741,174 +4585,305 @@ follows the last character of the match, if such a position exists.
If not bounded by an until clause, it will exhaust the entire line. If the
until clause matches, then the collection stops at that position,
and any bindings from that iteration are discarded.
-Like collect, coll also supports a last clause, which propagates variable
+Like collect, coll also supports an
+.cod3 until / last
+clause, which propagates variable
bindings and advances the position.
-Coll clauses nest, and variables bound within a coll are available to clauses
-within the rest of the coll clause, including the until clause, and appear as
-single values. The final list aggregation is only visible after the coll clause.
-
-The behavior of coll is troublesome, when delimited variables are used,
-because in text file formats, the material which separates items is not
-repeated after the last item. For instance, a comma-separated list usually does
-not appear as "a,b,c," but rather "a,b,c". There might not be any explicit
-termination - the last item might be at the very end of the line.
+.code coll
+clauses nest, and variables bound within a coll are available to clauses
+within the rest of the
+.code coll
+clause, including the
+.cod3 until / last
+clause, and appear as
+single values. The final list aggregation is only visible after the
+.code coll
+clause.
+
+The behavior of
+.code coll
+leads to difficulties when a delimited variable are used
+to match material which is delimiter separated rather than terminated.
+For instance, entries in a comma-separated files usually do
+not appear as
+.str a,b,c,
+but rather
+.strn a,b,c .
So for instance, the following result is not satisfactory:
+.IP code:
+.cblk
+\ @(coll)@a @(end)
+.cble
+.IP data:
+.cblk
+\ 1 2 3 4 5
+.cble
+.IP result:
+.cblk
+\ a[0]="1"
+ a[1]="2"
+ a[2]="3"
+ a[3]="4"
+.cble
+.PP
+
+The
+.code 5
+is missing because it isn't followed by a space, which the text-delimited
+variable match
+.str "@a "
+looks for. After matching "4 ", coll continues to look for
+matches, and doesn't find any. It is tempting to try to fix it like this:
+.IP code:
+.cblk
+\ @(coll)@a@/ ?/@(end)
+.cble
+.IP data:
+.cblk
+\ 1 2 3 4 5
+.cble
+.IP result:
+.cblk
+\ a[0]=""
+ a[1]=""
+ a[2]=""
+ a[3]=""
+ a[4]=""
+ a[5]=""
+ a[6]=""
+ a[7]=""
+ a[8]=""
+.cble
+.PP
- pattern: @(coll)@a @(end)
- data: 1 2 3 4 5
- result: a[0]="1"
- a[1]="2"
- a[2]="3"
- a[3]="4"
-
-What happened to the 5? After matching "4 ", coll continues to look for
-matches. It tries "5", which does not match, because it is not followed by a
-space. Then the line is consumed. So in this sequence, a valid item is either
-followed by a space, or by nothing. So it is tempting to try this:
-
- pattern: @(coll)@a@/ ?/@(end)
- data: 1 2 3 4 5
- result: a[0]=""
- a[1]=""
- a[2]=""
- a[3]=""
- a[4]=""
- a[5]=""
- a[6]=""
- a[7]=""
- a[8]=""
-
-however, the problem is that the regular expression / ?/ (match either a space
-or nothing), matches at any position. So when it is used as a variable
+The problem now is that the regular expression
+.code / ?/
+(match either a space or nothing), matches at any position.
+So when it is used as a variable
delimiter, it matches at the current position, which binds the empty string to
-the variable, the extent of the match being zero. In this situation, the coll
+the variable, the extent of the match being zero. In this situation, the
+.code coll
directive proceeds character by character. The solution is to use
positive matching: specify the regular expression which matches the item,
rather than a trying to match whatever follows. The collect directive will
-recognize all items which match the regular expression.
-
- pattern: @(coll)@{a /[^ ]+/}@(end)
- data: 1 2 3 4 5
- result: a[0]="1"
- a[1]="2"
- a[2]="3"
- a[3]="4"
- a[4]="5"
+recognize all items which match the regular expression:
+.IP code:
+.cblk
+\ @(coll)@{a /[^ ]+/}@(end)
+.cble
+.IP data:
+.cblk
+\ 1 2 3 4 5
+.cble
+.IP result:
+.cblk
+\ a[0]="1"
+ a[1]="2"
+ a[2]="3"
+ a[3]="4"
+ a[4]="5"
+.cble
+.PP
-The until clause can specify a pattern which, when recognized, terminates
+The
+.code until
+clause can specify a pattern which, when recognized, terminates
the collection. So for instance, suppose that the list of items may
or may not be terminated by a semicolon. We must exclude
the semicolon from being a valid character inside an item, and
add an until clause which recognizes a semicolon:
+.IP code:
+.cblk
+\ @(coll)@{a /[^ ;]+/}@(until);@(end);
+.cble
+.IP data:
+.cblk
+\ 1 2 3 4 5;
+.cble
+.IP result:
+.cblk
+\ a[0]="1"
+ a[1]="2"
+ a[2]="3"
+ a[3]="4"
+ a[4]="5"
+.cble
+.PP
- pattern: @(coll)@{a /[^ ;]+/}@(until);@(end);
-
- data: 1 2 3 4 5;
- result: a[0]="1"
- a[1]="2"
- a[2]="3"
- a[3]="4"
- a[4]="5"
-
-Semicolon or not, the items are collected properly.
+Whether followed by the semicolon or not, the items are collected properly.
-Note that the @(end) is followed by a semicolon. That's because
-when the @(until) clause meets a match, the matching material
+Note that the
+.code @(end)
+is followed by a semicolon. That's because
+when the
+.code @(until)
+clause meets a match, the matching material
is not consumed.
-Instead of regular expression hacks, this problem can be nicely
-solved with cases:
-
- pattern: @(coll)@(cases)@a @(or)@a@(end)@(end)
- data: 1 2 3 4 5
- result: a[0]="1"
- a[1]="2"
- a[2]="3"
- a[3]="4"
- a[4]="5"
-
-.SS Coll Keyword Parameters
+This repetition can, of course, be avoided by using
+.code @(last)
+instad of
+.code @(until)
+since
+.code @(last)
+consumes the terminating material.
+
+Instead of the above regular-expresion-based approach, this extraction problem
+can also be solved with
+.codn cases :
+.IP code:
+.cblk
+\ @(coll)@(cases)@a @(or)@a@(end)@(end)
+.cble
+.IP data:
+.cblk
+\ 1 2 3 4 5
+.cble
+.IP result:
+.cblk
+\ a[0]="1"
+ a[1]="2"
+ a[2]="3"
+ a[3]="4"
+ a[4]="5"
+.cble
+.PP
-The @(coll) directive takes most of the same parameters as @(collect).
+.coNP Keyword parameters in @ coll
+The
+.code @(coll)
+directive takes most of the same parameters as
+.codn @(collect) .
See the section Collect Keyword Parameters above.
-So for instance @(coll :gap 0) means that the collects must be
-consecutive, and @(coll :maxtimes 2) means that at most two matches
-will be collected. The :lines keyword does not exist, but there is
-an analogous :chars keyword.
-
-.SS The Flatten Directive.
-
-The flatten directive can be used to convert variables to one dimensional
+So for instance
+.code @(coll :gap 0)
+means that the collects must be
+consecutive, and
+.code @(coll :maxtimes 2)
+means that at most two matches
+will be collected. The
+.code :lines
+keyword does not exist, but there is
+an analogous
+.code :chars
+keyword.
+
+.dir flatten
+
+The
+.code flatten
+directive can be used to convert variables to one dimensional
lists. Variables which have a scalar value are converted to lists containing
that value. Variables which are multidimensional lists are flattened to
one-dimensional lists.
-Example (without @(flatten))
-
- pattern: @b
- @(collect)
- @(collect)
- @a
- @(end)
- @(end)
-
- data: 0
- 1
- 2
- 3
- 4
- 5
-
- result: b="0"
- a_0[0]="1"
- a_1[0]="2"
- a_2[0]="3"
- a_3[0]="4"
- a_4[0]="5"
-
-Example (with flatten):
-
- pattern: @b
- @(collect)
- @(collect)
- @a
- @(end)
- @(end)
- @(flatten a b)
-
- data: 0
- 1
- 2
- 3
- 4
- 5
-
- result: b[0]="0"
- a[0]="1"
- a[1]="2"
- a[2]="3"
- a[3]="4"
- a[4]="5"
-
-.SS The Merge Directive
-
-The merge directive provides a way of combining two or more variables
-in a somewhat complicated but very useful way.
+Example (without
+.codn @(flatten) )
+.IP code:
+.cblk
+\ @b
+ @(collect)
+ @(collect)
+ @a
+ @(end)
+ @(end)
+.cble
+.IP data:
+.cblk
+\ 0
+ 1
+ 2
+ 3
+ 4
+ 5
+.cble
+.IP result:
+.cblk
+\ b="0"
+ a_0[0]="1"
+ a_1[0]="2"
+ a_2[0]="3"
+ a_3[0]="4"
+ a_4[0]="5"
+.cble
+.PP
+
+Example (with
+.codn @(flatten) ):
+.IP code:
+.cblk
+\ @b
+ @(collect)
+ @(collect)
+ @a
+ @(end)
+ @(end)
+ @(flatten a b)
+.cble
+.IP data:
+.cblk
+\ 0
+ 1
+ 2
+ 3
+ 4
+ 5
+.cble
+.IP result:
+.cblk
+\ b="0"
+ a[0]="1"
+ a[1]="2"
+ a[2]="3"
+ a[3]="4"
+ a[4]="5"
+.cble
+.PP
+
+
+.dir merge
+
+The
+.code merge
+directive provides a way of combining two or more variables
+in a somewhat complicated but very useful way.
To understand what merge does we first have to define a property called depth.
-The depth of an atom such as a string is defined as 1. The depth of an empty
-list is 0. The depth of a nonempty list is one plus the depth of its deepest
-element. So for instance "foo" has depth 1, ("foo") has depth 2, and ("foo"
-("bar")) has depth three.
-
-We can now define the binary (two argument) merge operation as follows. (merge
-A B) first normalizes the values A and B such that they have equal depth.
-1. A value which has depth zero is put into a one element list.
-2. If either value has a smaller depth than the other, it is wrapped
+The depth of an atom such as a string is defined as
+.codn 1 .
+The depth of an empty
+list is
+.codn 0 .
+The depth of a nonempty list is one plus the depth of its deepest
+element. So for instance
+.str foo
+has depth 1,
+.cblk
+("foo")
+.cble
+has depth 2, and
+.cblk
+("foo" ("bar"))
+.cble
+has depth three.
+
+We can now define the binary (two argument) merge operation as follows.
+.IP 1
+.code (merge A B)
+first normalizes the values
+.code A
+and
+.code B
+such that they have equal depth.
+.IP 2
+A value which has depth zero is put into a one element list.
+.IP 3
+If either value has a smaller depth than the other, it is wrapped
in a list as many times as needed to give it equal depth.
Finally, the values are appended together.
+.PP
Merge takes more than two arguments. These are merged by a left reduction. The
leftmost two values are merged, and then this result is merged with the third
@@ -2917,31 +4892,51 @@ value, and so on.
Merge is useful for combining the results from collects at different
levels of nesting such that elements are at the appropriate depth.
-.SS The Cat Directive
+.dir cat
-The @(cat) directive converts a list variable into a single
+The
+.code cat
+directive converts a list variable into a single
piece of text. The syntax is:
- @(cat VAR [ SEP ])
+.cblk
+.mets @(cat < var <> [ sep ])
+.cble
-The SEP argument specifies a separating piece of text. If no separator
+The
+.meta sep
+argument specifies a separating piece of text. If no separator
is specified, then a single space is used.
Example:
+.IP code:
+.cblk
+\ @(coll)@{a /[^ ]+/}@(end)
+ @(cat a ":")
+.cble
+.IP data:
+.cblk
+\ 1 2 3 4 5
+.cble
+.IP result:
+.cblk
+\ a="1:2:3:4:5"
+.cble
+.PP
- pattern: @(coll)@{a /[^ ]+/}@(end)
- @(cat a ":")
- data: 1 2 3 4 5
- result: a="1:2:3:4:5"
-
-
-.SS The Bind Directive
+.dir bind
-The syntax of the @(bind) directive is:
+The syntax of the
+.code bind
+directive is:
- @(bind pattern expression { keyword value }*)
+.cblk
+.mets @(bind < pattern < expression >> { keyword << value }*)
+.cble
-The @(bind) directive is a kind of pattern match, which matches one or more
+The
+.code bind
+directive is a kind of pattern match, which matches one or more
variables on the left hand side pattern to the value of a variable on the
right hand side. The right hand side variable must have a binding, or else the
directive fails. Any variables on the left hand side which are unbound receive
@@ -2950,165 +4945,357 @@ are already bound must match their corresponding value, or the bind fails. Any
variables which are already bound and which do match their corresponding value
remain unchanged (the match can be inexact).
-The simplest bind is of one variable against itself, for instance bind A
-against A:
+The simplest bind is of one variable against itself, for instance bind
+.code A
+against
+.codn A :
+.cblk
@(bind A A)
-
-This will fail if A is not bound, (and complain loudly). If A is bound, it
-succeeds, since A matches A.
+.cble
+
+This will fail if
+.code A
+is not bound, (and complain loudly). If
+.code A
+is bound, it
+succeeds, since
+.code A
+matches
+.codn A .
The next simplest bind binds one variable to another:
+.cblk
@(bind A B)
+.cble
-Here, if A is unbound, it takes on the same value as B. If A is bound, it has
-to match B, or the bind fails. Matching means that either
+Here, if
+.code A
+is unbound, it takes on the same value as
+.codn B .
+If
+.code A
+is bound, it has
+to match
+.codn B ,
+or the bind fails. Matching means that either
.IP -
-A and B are the same text
+.code A
+and
+. code B
+are the same text
.IP -
-A is text, B is a list, and A occurs within B.
+.code A
+is text,
+.code B
+is a list, and
+.code A
+occurs within
+.codn B .
.IP -
-vice versa: B is text, A is a list, and B occurs within A.
+vice versa:
+.code B
+is text,
+.code A
+is a list, and
+.code B
+occurs within
+.codn A .
.IP -
-A and B are lists and are either identical, or one is
+.code A
+and
+.code B
+are lists and are either identical, or one is
found as substructure within the other.
.PP
The right hand side does not have to be a variable. It may be some other
object, like a string, quasiliteral, regexp, or list of strings, et cetera. For
instance
+.cblk
@(bind A "ab\etc")
-
-will bind the string "ab\etc" (the letter a, b, a tab character, and c)
-to the variable A if A is unbound. If A is bound, this will fail unless
-A already contains an identical string. However, the right hand side of a bind
+.cble
+
+will bind the string
+.str ab\etc
+to the variable
+.code A
+if
+.code A
+is unbound. If
+.code A
+is bound, this will fail unless
+.code A
+already contains an identical string. However, the right hand side of a bind
cannot be an unbound variable, nor a complex expression that contains unbound
variables.
-The left hand side of a bind can be a nested list pattern containing variables.
-The last item of a list at any nesting level can be preceded by a dot, which
-means that the variable matches the rest of the list from that position.
-
-Example: suppose that the list A contains ("now" "now" "brown" "cow"). Then the
-directive @(bind (H N . C) A), assuming that H, N and C are unbound variables,
-will bind H to "how", N to "now", and C to the remainder of the list ("brown"
-"cow").
-
-Example: suppose that the list A is nested to two dimensions and contains
-(("how" "now") ("brown" "cow")). Then @(bind ((H N) (B C)) A)
-binds H to "how", N to "now", B to "brown" and C to "cow".
-
-The dot notation may be used at any nesting level. it must be preceded and
-followed by a symbol: the forms (.) (. X) and (X .) are invalid.
+The left hand side of
+.code bind
+can be a nested list pattern containing variables.
+The last item of a list at any nesting level can be preceded by a
+.code .
+(dot), which means that the variable matches the rest of the list from that
+position.
+
+Example: suppose that the list A contains
+.cblk
+("now" "now" "brown" "cow").
+.cble
+Then the
+directive
+.codn "@(bind (H N . C) A)" ,
+assuming that
+.codn H ,
+.code N
+and
+.code C are unbound variables,
+will bind
+.code H
+to
+.strn how ,
+code N
+to
+.strn now ,
+and
+.code C
+to the remainder of the list
+.cblk
+("brown" "cow").
+.cble
+
+Example: suppose that the list
+.code A
+is nested to two dimensions and contains
+.cblk
+(("how" "now") ("brown" "cow")).
+.cble
+Then
+.code @(bind ((H N) (B C)) A)
+binds
+.code H to
+.strn how ,
+.code N
+to
+.strn now ,
+.code B
+to
+.str brown
+and
+.code C
+to
+.strn cow .
+
+The dot notation may be used at any nesting level. it must be followed
+by an item. The forms
+.code (.)
+and
+.code (X .)
+are invalid, but
+.code (. X)
+is valid and equivalent to
+.codn X .
The number of items in a left pattern match must match the number of items in
-the corresponding right side object. So the pattern () only matches
-an empty list. The notation () and nil means exactly the same thing.
-
-The symbols nil, t and keyword symbols may be used on either side.
-They represent themselves. For example @(bind :foo :bar) fails,
-but @(bind :foo :foo) succeeds since the two sides denote the same
+the corresponding right side object. So the pattern
+.code ()
+only matches
+an empty list. The notations
+.code ()
+and
+.code nil
+mean exactly the same thing.
+
+The symbols
+.codn nil ,
+.code t
+and keyword symbols may be used on either side.
+They represent themselves. For example
+.code @(bind :foo :bar)
+fails,
+but
+.code @(bind :foo :foo)
+succeeds since the two sides denote the same
keyword symbol object.
-.SS Keywords in The Bind Directive
-
-The Bind directive accepts these keywords:
+.coNP Keywords in the @ bind directive
+The
+.code bind
+directive accepts these keywords:
-.IP :lfilt
-The argument to :lfilt is a filter specification. When the left side pattern
+.coIP :lfilt
+The argument to
+.code :lfilt
+is a filter specification. When the left side pattern
contains a binding which is therefore matched against its counterpart from the
right side expression, the left side is filtered through the filter specified
-by :lfilt for the purposes of the comparison. For example:
+by
+.code :lfilt
+for the purposes of the comparison. For example:
+.cblk
@(bind "a" "A" :lfilt :upcase)
+.cble
produces a match, since the left side is the same as the right after
filtering through the :upcase filter.
-.IP :rfilt
-The argument to :rfilt is a filter specification. The specified filter is
+.coIP :rfilt
+The argument to
+.code :rfilt
+is a filter specification. The specified filter is
applied to the right hand side material prior to matching it against
the left side. The filter is not applied if the left side is a variable
with no binding. It is only applied to determine a match. Binding takes
place the unmodified right hand side object.
-Example, the following produces a match:
+For example, the following produces a match:
+.cblk
@(bind "A" "a" :rfilt :upcase)
+.cble
-.IP :filter
+.coIP :filter
This keyword is a shorthand to specify both filters to the same value.
-So for instance :filter :upcase is equivalent to :lfilt :upcase :rfilt :upcase.
+For instance
+.code :filter :upcase
+is equivalent to
+.codn ":lfilt :upcase :rfilt :upcase" .
For a description of filters, see Output Filtering below.
-Of course, compound filters like (:from_html :upcase) are supported with
-all these keywords. The filters apply across arbitrary patterns and nested data.
+Of course, compound filters like
+.code (:from_html :upcase)
+are supported with all these keywords. The filters apply across arbitrary
+patterns and nested data.
Example:
+.cblk
@(bind (a b c) ("A" "B" "C"))
@(bind (a b c) (("z" "a") "b" "c") :rfilt :upcase)
-
-Here, the first bind establishes the values for a, b and c, and the second bind
-succeeds, because the value of a matches the second element of the list ("z"
-"a") if it is upcased, and likewise b matches "b" and c matches "c" if these
-are upcased.
-
-.SS The Set Directive
-
-The @(set) directive resembles bind, but is not a pattern match. It overwrites
+.cble
+
+Here, the first bind establishes the values for
+.codn a ,
+.code b
+and
+.codn c ,
+and the second bind
+succeeds, because the value of a matches the second element of the list
+.code ("z" "a")
+if it is upcased, and likewise
+.code b
+matches
+.str "b"
+and
+.code c
+matches
+.str c
+if these are upcased.
+
+.dir set
+
+The
+.code set
+directive syntactically resembles
+.codn bind ,
+but is not a pattern match. It overwrites
the previous values of variables with new values from the right hand side.
-Each variable that is assigned must have an existing binding.
+Each variable that is assigned must have an existing binding:
+.code set
+will not induce binding.
Examples follow.
-Store the value of A back into A, achieving nothing:
+Store the value of
+.code A
+back into
+.codn A ,
+an operation with no effect:
+.cblk
@(set A A)
+.cble
-Exchange the values of A and B:
+Exchange the values of
+.code A
+and
+.codn B :
+.cblk
@(set (A B) (B A))
+.cble
-Store a string into A:
+Store a string into
+.codn A :
+.cblk
@(set A "text")
+.cble
-Store a list into A:
+Store a list into
+.codn A :
+.cblk
@(set A ("line1" "line2"))
-
-Destructuring assignment. D assumed to contain the list
-
+.cble
+
+Destructuring assignment.
+.code A
+ends up with
+.strn A ,
+.code B
+ends up with
+.cblk
+("B1" "B2")
+.cble
+and
+.code C
+binds to
+.cblk
+("C1" "C2").
+.cble
+
+.cblk
@(bind D ("A" ("B1" "B2") "C1" "C2"))
@(bind (A B C) (() () ()))
@(set (A B . C) D)
-
-A ends up with "A", B ends up with ("B1" "B2") and C gets ("C1" and "C2").
-
-.SS The Rebind Directive
-
-The @(rebind) directive resembles @(set) but it is not an assignment.
-It combines the semantics of @(local), @(bind) and @(set).
+.cble
+
+.dir rebind
+
+The
+.code rebind
+directive resembles
+.code set
+but it is not an assignment.
+It combines the semantics of
+.codn local ,
+.code bind
+and
+.codn set .
The expression on the right hand side is evaluated in the current
environment. Then the variables in the pattern on the left are introduced
as new bindings, whose values come from the pattern.
-Rebind makes it easy to create temporary bindings based on existing
-bindings.
+.code rebind
+makes it easy to create temporary bindings based on existing bindings.
+.cblk
@(define pattern-function (arg))
@;; inside a pattern function:
@(rebind recursion-level @(+ recursion-level 1))
@;; ...
@(end)
+.cble
When the function terminates, the previous value of recursion-level
is restored. The effect is like the following, but much easier
to write and faster to execute:
+.cblk
@(define pattern-function (arg))
@;; inside a pattern function:
@(local temp)
@@ -3117,20 +5304,30 @@ to write and faster to execute:
@(set recursion-level @(+ temp 1))
@;; ...
@(end)
+.cble
-.SS The Forget Directive
+.dir forget
-The Forget Directive has two spellings @(forget) and @(local).
+The
+.code forget
+has two spellings:
+.code @(forget)
+and
+.codn @(local).
The arguments are one or more symbols, for example:
+.cblk
@(forget a)
@(local a b c)
+.cble
this can be written
+.cblk
@(local a)
@(local a b c)
+.cble
Directives which follow the forget or local directive no longer see
any bindings for the symbols mentioned in that directive, and
@@ -3138,7 +5335,9 @@ can establish new bindings.
It is not an error if the bindings do not exist.
-It is strongly recommended to use @(local) spelling in functions,
+It is strongly recommended to use the
+.code @(local)
+spelling in functions,
because the forgetting action simulates local variables:
for the given symbols, the machine forgets any earlier variables
from outside of the function, and consequently, any new bindings
@@ -3147,69 +5346,141 @@ functions suppress the propagation of variables that are not
in their parameter list, so these locals will be automatically
forgotten when the function terminates.)
-.SH BLOCKS
+.dir do
-.SS Introduction
+The syntax of
+.code @(do)
+is:
-Blocks are sections of a query which are denoted by a name. Blocks denoted by
-the name nil are understood as anonymous.
+.cblk
+.mets @(do << lisp-expression )
+.cble
-The @(block NAME) directive introduces a named block, except when the name is
-the word nil. The @(block) directive introduces an unnamed block, equivalent
-to @(block nil).
+The do directive evaluates a TXR Lisp expression. (See TXR LISP far
+below.) The value of the expression is ignored, and matching continues
+continues with the directives which follow the
+.code do
+directive, if any.
-The @(skip) and @(collect) directives introduce implicit anonymous blocks,
-as do function bodies.
+In the context of the
+.code do
+directive, the expression should not be introduced by the
+.code @
+symbol; it is expected to be a Lisp expression.
+
+Example:
+
+.cblk
+ @; match text into variables a and b, then insert into hash table h
+ @(bind h (hash :equal-based))
+ @a:@b
+ @(do (set [h a] b))
+.cble
+
+.SH* BLOCKS
+.SS* Overview
+Blocks are sections of a query which are either denoted by a name,
+or are anonymous. They may nest: blocks can occur within blocks
+and other constructs.
Blocks are useful for terminating parts of a pattern matching search
prematurely, and escaping to a higher level. This makes blocks not only
useful for simplifying the semantics of certain pattern matches,
-but also an optimization tool.
+but also an optimization tool.
Judicious use of blocks and escapes can reduce or eliminate the amount of
backtracking that TXR performs.
-.SS Block Scope
-
-The names of blocks are in a distinct namespace from the variable binding
-space. So @(block foo) has no interaction with the variable @foo.
+.dir block
+
+The
+.cblk
+.meti @(block << name )
+.cble
+directive introduces a named block, except when
+.meta name
+is the symbol
+.codn nil .
+The
+.code @(block)
+directive introduces an unnamed block, equivalent
+to
+.codn "@(block nil)" .
+
+The
+.code @(skip)
+and
+.code @(collect)
+directives introduce implicit anonymous blocks,
+as do function bodies.
-A block extends from the @(block ...) directive which introduces it,
-until the matching @(end), and may be empty. For instance:
+.SS* Block Scope
+The names of blocks are in a distinct namespace from the variable binding
+space. So
+.code @(block foo)
+is unrelated to the variable
+.codn @foo .
+
+A block extends from the
+.code @(block ...)
+directive which introduces it,
+until the matching
+.codn @(end) ,
+and may be empty. For instance:
+
+.cblk
@(some)
abc
@(block foo)
xyz
@(end)
@(end)
-
-Here, the block foo occurs in a @(some) clause, and so it extends to the @(end)
-which terminates the block. After that @(end), the name foo is not
-associated with a block (is not "in scope"). The second @(end) terminates
-the @(some) block.
-
-The implicit anonymous block introduced by @(skip) has the same scope
-as the @(skip): it extends over all of the material which follows the skip,
+.cble
+
+Here, the block foo occurs in a
+.code @(some)
+clause, and so it extends to the
+.code @(end)
+which terminates the block. After that
+.codn @(end) ,
+the name foo is not
+associated with a block (is not "in scope"). The second
+.code @(end)
+terminates
+the
+.code @(some)
+block.
+
+The implicit anonymous block introduced by
+.code @(skip)
+has the same scope
+as the
+.codn @(skip) :
+it extends over all of the material which follows the skip,
to the end of the containing subquery.
-.SS Block Nesting
+.SS* Block Nesting
Blocks may nest, and nested blocks may have the same names as blocks in
which they are nested. For instance:
+.cblk
@(block)
@(block)
...
@(end)
@(end)
+.cble
is a nesting of two anonymous blocks, and
+.cblk
@(block foo)
@(block foo)
@(end)
@(end)
+.cble
is a nesting of two named blocks which happen to have the same name.
When a nested block has the same name as an outer block, it creates
@@ -3217,63 +5488,82 @@ a block scope in which the outer block is "shadowed"; that is to say,
directives which refer to that block name within the nested block refer to the
inner block, and not to the outer one.
-.SS Block Semantics
+.SS* Block Semantics
A block normally does nothing. The query material in the block is evaluated
-normally. However, a block serves as a termination point for @(fail) and
-@(accept) directives which are in scope of that block and refer to it.
+normally. However, a block serves as a termination point for
+.code @(fail)
+and
+.code @(accept)
+directives which are in scope of that block and refer to it.
The precise meaning of these directives is:
-.IP "@(fail NAME)"
-
-Immediately terminate the enclosing query block called NAME, as if that block
+.meIP @(fail << name )
+Immediately terminate the enclosing query block called
+.metn name ,
+as if that block
failed to match anything. If more than one block by that name encloses
the directive, the inner-most block is terminated. No bindings emerge from
a failed block.
-.IP @(fail)
-
+.coIP @(fail)
Immediately terminate the innermost enclosing anonymous block, as if
that block failed to match.
-If the implicit block introduced by @(skip) is terminated in this manner,
-this has the effect of causing the skip itself to fail. I.e. the behavior
+If the implicit block introduced by
+.code @(skip)
+is terminated in this manner,
+this has the effect of causing
+.code skip
+itself to fail. I.e. the behavior
is as if skip search did not find a match for the trailing material,
except that it takes place prematurely (before the end of the available
data source is reached).
-If the implicit block associated with a @(collect) is terminated this way,
-then the entire collect fails. This is a special behavior, because a
-collect normally does not fail, even if it matches and collects nothing!
+If the implicit block associated with a
+.code @(collect)
+is terminated this way,
+then the entire
+.code collect
+fails. This is a special behavior, because a
+collect normally does not fail, even if it matches nothing and collects nothing!
To prematurely terminate a collect by means of its anonymous block, without
-failing it, use @(accept).
+failing it, use
+.codn @(accept) .
-.IP "@(accept NAME)"
-
-Immediately terminate the enclosing query block called NAME, as if that block
+.meIP @(accept << name )
+Immediately terminate the enclosing query block called
+.metn name ,
+as if that block
successfully matched. If more than one block by that name encloses the
directive, the inner-most block is terminated. Any bindings established within
that block until this point emerge from that block.
-.IP @(accept)
-
+.coIP @(accept)
Immediately terminate the innermost enclosing anonymous block, as if
that block successfully matched. Any bindings established within
that block until this point emerge from that block.
-If the implicit block introduced by @(skip) is terminated in this manner,
+If the implicit block introduced by
+.code @(skip)
+is terminated in this manner,
this has the effect of causing the skip itself to succeed, as if
-all of the trailing material successfully matched.
+all of the trailing material had successfully matched.
-If the implicit block associated with a @(collect) is terminated this way,
+If the implicit block associated with a
+.code @(collect)
+is terminated this way,
then the collection stops. All bindings collected in the current iteration of
the collect are discarded. Bindings collected in previous iterations are
retained, and collated into lists in accordance with the semantics of collect.
-Example: alternative way to @(until) termination:
+Example: alternative way to achieve
+.code @(until)
+termination:
+.cblk
@(collect)
@ (maybe)
---
@@ -3281,23 +5571,34 @@ Example: alternative way to @(until) termination:
@ (end)
@LINE
@(end)
-
-This query will collect entire lines into a list called LINE. However,
-if the line --- is matched (by the embedded @(maybe)), the collection
-is terminated. Only the lines up to, and not including the --- line,
-are collected. The effect is identical to:
-
+.cble
+
+This query will collect entire lines into a list called
+.codn LINE .
+However,
+if the line
+.code ---
+is matched (by the embedded
+.codn @(maybe)),
+the collection
+is terminated. Only the lines up to, and not including the
+.code ---
+line, are collected. The effect is identical to:
+
+.cblk
@(collect)
@LINE
@(until)
---
@(end)
+.cble
The difference (not relevant in these examples) is that the until clause has
visibility into the bindings set up by the main clause.
However, the following example has a different meaning:
+.cblk
@(collect)
@LINE
@ (maybe)
@@ -3305,155 +5606,243 @@ However, the following example has a different meaning:
@ (accept)
@ (end)
@(end)
+.cble
Now, lines are collected until the end of the data source, or until a line is
-found which is followed by a --- line. If such a line is found,
+found which is followed by a
+.code ---
+line. If such a line is found,
the collection stops, and that line is not included in the collection!
-The @(accept) terminates the process of the collect body, and so the
-action of collecting the last @LINE binding into the list is not performed.
+The
+.code @(accept)
+terminates the process of the collect body, and so the
+action of collecting the last
+.code @LINE
+binding into the list is not performed.
+.PP
-.SS Data Extent of Terminated Blocks
+.SS* Data Extent of Terminated Blocks
A query block may have matched some material prior to being terminated by
-accept. In that case, it is deemed to have only matched that material,
+.codn accept .
+In that case, it is deemed to have only matched that material,
and not any material which follows. This may matter, depending on the context
in which the block occurs.
Example:
+.IP code:
+.cblk
+\ @(some)
+ @(block foo)
+ @first
+ @(accept foo)
+ @ignored
+ @(end)
+ @second
+.cble
+.IP data:
+.cblk
+\ 1
+ 2
+ 3
+.cble
+.IP result:
+.cblk
+\ first="1"
+ second="2"
+.cble
+.PP
- Query: @(some)
- @(block foo)
- @first
- @(accept foo)
- @ignored
- @(end)
- @second
-
- Data: 1
- 2
- 3
-
- Output (-B): first="1"
- second="2"
-
-At the point where the accept occurs, the foo block has matched the first line,
-bound the text "1" to the variable @first. The block is then terminated.
-Not only does the @first binding emerge from this terminated block, but
+At the point where the
+.code accept
+occurs, the foo block has matched the first line,
+bound the text
+.str 1
+to the variable
+.codn @first .
+The block is then terminated.
+Not only does the
+.code @first
+binding emerge from this terminated block, but
what also emerges is that the block advanced the data past the first line to
-the second line. So next, the @(some) directive ends, and propagates the
-bindings and position. Thus the @second which follows then matches the second
-line and takes the text "2".
+the second line. Next, the
+.code @(some)
+directive ends, and propagates the
+bindings and position. Thus the
+.code @second
+which follows then matches the second
+line and takes the text
+.strn 2 .
In the following query, the foo block occurs inside a maybe clause.
-Inside the foo block there is a @(some) clause. Its first subclause
-matches variable @first and then terminates block foo. Since block foo is
-outside of the @(some) directive, this has the effect of terminating the
-@(some) clause:
-
- Query: @(maybe)
- @(block foo)
- @ (some)
- @first
- @ (accept foo)
- @ (or)
- @one
- @two
- @three
- @four
- @ (end)
- @(end)
- @second
-
- Data: 1
- 2
- 3
- 4
- 5
-
- Output (-B): first="1"
- second="2"
-
-The second clause of the @(some) directive, namely:
+Inside the foo block there is a
+.code @(some)
+clause. Its first subclause
+matches variable
+.code @first
+and then terminates block foo. Since block foo is
+outside of the
+.code @(some)
+directive, this has the effect of terminating the
+.code @(some)
+clause:
+.IP code:
+.cblk
+\ @(maybe)
+ @(block foo)
+ @ (some)
+ @first
+ @ (accept foo)
+ @ (or)
+ @one
+ @two
+ @three
+ @four
+ @ (end)
+ @(end)
+ @second
+.cble
+.IP data:
+.cblk
+\ 1
+ 2
+ 3
+ 4
+ 5
+.cble
+.IP result:
+.cblk
+\ first="1"
+ second="2"
+.cble
+.PP
+
+The second clause of the
+.code @(some)
+directive, namely:
+.cblk
@one
@two
@three
@four
+.cble
is never processed. The reason is that subclauses are processed in top
to bottom order, but the processing was aborted within the
-first clause the @(accept foo). The @(some) construct never had the
+first clause the
+.codn "@(accept foo)" .
+The
+.code @(some)
+construct never gets the
opportunity to match four lines.
-If the @(accept foo) line is removed from the above query, the output
+If the
+.code @(accept foo)
+line is removed from the above query, the output
is different:
+.IP code:
+.cblk
+\ @(maybe)
+ @(block foo)
+ @ (some)
+ @first
+ @# <-- @(accept foo) removed from here!!!
+ @ (or)
+ @one
+ @two
+ @three
+ @four
+ @ (end)
+ @(end)
+ @second
+.cble
+.IP data:
+.cblk
+\ 1
+ 2
+ 3
+ 4
+ 5
+.cble
+.IP result:
+.cblk
+\ first="1"
+ one="1"
+ two="2"
+ three="3"
+ four="4"
+ second="5"
+.cble
+.PP
- Query: @(maybe)
- @(block foo)
- @ (some)
- @first
- @# <-- @(accept foo) removed from here!!!
- @ (or)
- @one
- @two
- @three
- @four
- @ (end)
- @(end)
- @second
-
- Data: 1
- 2
- 3
- 4
- 5
-
- Output (-B): first="1"
- one="1"
- two="2"
- three="3"
- four="4"
- second="5"
-
-Now, all clauses of the @(some) directive have the opportunity to match.
+Now, all clauses of the
+.code @(some)
+directive have the opportunity to match.
The second clause grabs four lines, which is the longest match.
-And so, the next line of input available for matching is 5, which goes
-to the @second variable.
+And so, the next line of input available for matching is
+.codn 5 ,
+which goes
+to the
+.code @second
+variable.
-.SS Interaction between Trailer and Accept Directives
+.coSS Interaction Between the @ trailer and @ accept Directives
-If one of the clauses which follow a @(trailer) request a successful
-termination to an outer block via @(accept), then @(trailer) intercepts
-the transfer and adjusts the data extent to the position that it was given.
+If one of the clauses which follow a
+.code @(trailer)
+requests a successful
+termination to an outer block via
+.codn @(accept) ,
+then
+.code @(trailer)
+intercepts the escape and adjusts the data extent to the position
+that it was given.
Example:
+.IP code:
+.cblk
+\ @(block)
+ @(trailer)
+ @line1
+ @line2
+ @(accept)
+ @(end)
+ @line3
+.cble
+.IP data:
+.cblk
+\ 1
+ 2
+ 3
+.cble
+.IP result:
+.cblk
+\ line1="1"
+ line2="2"
+ line3="1"
+.cble
+.PP
- Query: @(block)
- @(trailer)
- @line1
- @line2
- @(accept)
- @(end)
- @line3
-
- Data: 1
- 2
- 3
-
- Output (-B): line1="1"
- line2="2"
- line3="1"
-
-The variable line3 is bound to 1 because although the @(accept) yields a data
-position which is advanced to the third line, this is intercepted by @(trailer)
-and adjusted back to the first line.
-
-Directives other than @(trailer) have no such special interaction with accept.
-
-.SH FUNCTIONS
-
-.SS Introduction
-
+The variable
+.code line3
+is bound to
+.str 1
+because although
+.code @(accept)
+yields a data
+position which has advanced to the third line, this is intercepted by
+.code @(trailer)
+and adjusted back to the first line. Neglecting to do this adjustment
+would violate the semantics of
+.codn trailer .
+
+Directives other than
+.code @(trailer)
+have no such special interaction with accept.
+
+.SH* FUNCTIONS
+.SS* Overview
.B TXR
functions allow a query to be structured to avoid repetition.
On a theoretical note, because
@@ -3506,39 +5895,67 @@ argument.
Example:
- @(define collect_words (list))
+.cblk
+ @(define collect-words (list))
@(coll)@{list /[^ \et]+/}@(end)
@(end)
+.cble
-The above function "collect_words" contains a query which collects words from a
+The above function
+.code collect-words
+contains a query which collects words from a
line (sequences of characters other than space or tab), into the list variable
-called "list". This variable is named in the parameter list of the function,
+called
+.codn list .
+This variable is named in the parameter list of the function,
therefore, its value, if it has one, is permitted to escape from the function
call.
Suppose the input data is:
+.cblk
Fine summer day
+.cble
and the function is called like this:
- @(collect_words wordlist)
+.cblk
+ @(collect-words wordlist)
+.cble
-The result with txr -B is:
+The result (with
+.codn "txr -B" )
+is:
+.cblk
wordlist[0]=Fine
wordlist[1]=summer
wordlist[1]=day
-
-How it works is that in the function call @(collect_words wordlist),
-"wordlist" is an unbound variable. The parameter corresponding to that
-unbound variable is the parameter "list". Therefore, that parameter
+.cble
+
+How it works is that in the function call
+.codn "@(collect-words wordlist)" ,
+.code wordlist
+is an unbound variable. The parameter corresponding to that
+unbound variable is the parameter
+.codn list .
+Therefore, that parameter
is unbound over the body of the function. The function body collects the
-words of "Fine summer day" into the variable "list", and then
+words of
+.str Fine summer day
+into the variable
+.codn list,
+and then
yields the that binding. Then the function call completes by
-noticing that the function parameter "list" now has a binding, and
-that the corresponding argument "wordlist" has no binding. The binding
-is thus transferred to the "wordlist" variable. After that, the
+noticing that the function parameter
+.code list
+now has a binding, and
+that the corresponding argument
+.code wordlist
+has no binding. The binding
+is thus transferred to the
+.code wordlist
+variable. After that, the
bindings produced by the function are thrown away. The only enduring
effects are:
.IP -
@@ -3546,7 +5963,9 @@ the function matched and consumed some input; and
.IP -
the function succeeded; and
.IP -
-the wordlist variable now has a binding.
+the
+.code wordlist
+variable now has a binding.
.PP
Another way to understand the parameter behavior is that function
parameters behave like proxies which represent their arguments. If an argument
@@ -3559,54 +5978,103 @@ function goes out of scope.
Within the function, both the original variable and the proxy are
visible simultaneously, and are independent. What if a function binds both of
-them? Suppose a function has a parameter called P, which is called
-with an argument A, and then in the function @A and @P are bound. This is
+them? Suppose a function has a parameter called
+.codn P ,
+which is called with an argument
+.codn A ,
+which is an unbound variable, and then, in the function, both
+.code A
+and
+.code P
+bound. This is
permitted, and they can even be bound to different values. However, when the
-function terminates, the local binding of A simply disappears (because,
-remember, the symbol A is not a member of the list of parameters).
-Only the value bound to P emerges, and is bound to A, which still appears
-unbound at that point.
-
-.SS Definition Syntax
+function terminates, the local binding of A simply disappears (because
+the symbol
+.code A
+is not among the paramters of the function).
+Only the value bound to
+.code P
+emerges, and is bound to
+.codn A ,
+which still appears unbound at that point. The
+.code P
+binding disappears also, and the net effect is that
+.code A
+is now bound. The "proxy" binding of
+.code A
+thorugh the parameter
+.code P
+"wins" the conflict with the direct binding.
+
+.SS* Definition Syntax
Function definition syntax comes in two flavors: vertical and horizontal.
Horizontal definitions actually come in two forms, the distinction
between which is hardly noticeable, and the need for which is
made clear below.
-A function definition begins with a @(define ...) directive. For vertical
+A function definition begins with a
+.code @(define ...)
+directive. For vertical
functions, this is the only element in a line.
-The define symbol must be followed by a symbol, which is the name of the
+The
+.code define
+symbol must be followed by a symbol, which is the name of the
function being defined. After the symbol, there is a parenthesized optional
-argument list. If there is no such list, or if the list is specified as () or
-the symbol "nil" then the function has no parameters. Examples of valid define
+argument list. If there is no such list, or if the list is specified as
+.code ()
+or
+the symbol
+.code nil
+then the function has no parameters. Examples of valid
+.code define
syntax are:
+.cblk
@(define foo)
@(define bar ())
@(define match (a b c))
+.cble
If the define directive is followed by more material on the same line, then
it defines a horizontal function:
- @(define match_x)x@(end)
+.cblk
+ @(define match-x)x@(end)
+.cble
If the define is the sole element in a line, then it
is a vertical function, and the function definition continues below:
- @(define match_x)
+.cblk
+ @(define match-x)
x
@(end)
+.cble
The difference between the two is that a horizontal function matches
characters within a line, whereas a vertical function matches lines
-within a stream. The former match_x matches the character x, advancing
-to the next character position. The latter match_x matches a line consisting
-of the character x, advancing to the next line.
-
-Material between @(define) and @(end) is the function body. The define
-directive may be followed directly by the @(end) directive, in which case the
+within a stream. The former
+.code match-x
+matches the character
+.codn x ,
+advancing
+to the next character position. The latter
+.code match-x
+matches a line consisting
+of the character
+.codn x ,
+advancing to the next line.
+
+Material between
+.code @(define)
+and
+.code @(end)
+is the function body. The define
+directive may be followed directly by the
+.code @(end)
+directive, in which case the
function has an empty body.
Functions may be nested within function bodies. Such local functions have
@@ -3615,41 +6083,55 @@ and in any functions invoked from that body.
The body of a function is an anonymous block. (See BLOCKS above).
-.SS Two Forms of The Horizontal Function
+.SS* Two Forms of The Horizontal Function
If a horizontal function is defined as the only element of a line,
it may not be followed by additional material. The following
construct is erroneous:
+.cblk
@(define horiz (x))@foo:@bar@(end)lalala
+.cble
This kind of definition is actually considered to be in the vertical context,
and like other directives that have special effects and that do not match
anything, it does not consume a line of input. If the above syntax were
allowed, it would mean that the line would not only define a function but also
-match "lalala". This would, in turn, would mean that the @(define)...@(end) is
+match
+.codn "lalala" .
+This would, in turn, would mean that the
+.code @(define)...@(end)
+is
actually in horizontal mode, and so it matches a span of zero characters within
-a line (which means that is would require a line of input to match: a nasty
-thing for a non-matching directive to do!)
+a line (which means that is would require a line of input to match: a
+surprising behavior for a non-matching directive!)
A horizontal function can be defined in an actual horizontal context. This
occurs if its is in a line where it is preceded by other material.
For instance:
+.cblk
X@(define fun)...@(end)Y
+.cble
-This is a query line which must match the text XY. It also defines the function
-fun. The main use of this form is for nested horizontal functions:
+This is a query line which must match the text
+.codn XY .
+It also defines the function
+.codn fun .
+The main use of this form is for nested horizontal functions:
+.cblk
@(define fun)@(define local_fun)...@(end)@(end)
+.cble
-.SS Vertical-Horizontal Overloading
+.SS* Vertical-Horizontal Overloading
A function of the same name may be defined as both vertical and horizontal.
Both functions are available at the same time. Which one is used by
-a call is resolved by context. See the section Vertical Versus Horizontal Calls below.
+a call is resolved by context. See the section Vertical Versus Horizontal Calls
+below.
-.SS Call Syntax
+.SS* Call Syntax
A function is invoked by compound directive whose first symbol is the name of
that function. Additional elements in the directive are the arguments.
@@ -3657,45 +6139,92 @@ Arguments may be symbols, or other objects like string and character
literals, quasiliterals ore regular expressions.
Example:
+.IP code:
+.cblk
+\ @(define pair (a b))
+ @a @b
+ @(end)
+ @(pair first second)
+ @(pair "ice" cream)
+.cble
+.IP data:
+.cblk
+\ one two
+ ice milk
+.cble
+.IP result:
+.cblk
+\ first="one"
+ second="two"
+ cream="milk"
+.cble
+.PP
- Query: @(define pair (a b))
- @a @b
- @(end)
- @(pair first second)
- @(pair "ice" cream)
-
- Data: one two
- ice milk
-
- Output (-B) first="one"
- second="two"
- cream="milk"
-
-The first call to the function takes the line "one two". The parameter "a"
-takes "one" and parameter b takes "two". These are rebound to the arguments
-first and second. The second call to the function binds the a parameter
-to the word "ice", and the b is unbound, because the
-corresponding argument "cream" is unbound. Thus inside the function, @a
-is forced to match "ice". Then a space is matched and @b collects the text
-"milk". When the function returns, the unbound "cream" variable gets this value.
+The first call to the function takes the line
+.strn "one two" .
+The parameter
+.code a
+takes
+.str one
+and parameter
+.code b
+takes
+.strn two .
+These are rebound to the arguments
+.code first
+and
+.codn second .
+The second call to the function binds the a parameter to the word
+.strn "ice" ,
+and the
+.code b
+is unbound, because the
+corresponding argument
+.code cream
+is unbound. Thus inside the function,
+.code a
+is forced to match
+.codn "ice" .
+Then a space is matched and
+.code b
+collects the text
+.strn milk .
+When the function returns, the unbound
+.str cream
+variable gets this value.
If a symbol occurs multiple times in the argument list, it constrains
both parameters to bind to the same value. That is to say, all parameters
which, in the body of the function, bind a value, and which are all derived
from the same argument symbol must bind to the same value. This is settled when
the function terminates, not while it is matching. Example:
+.IP code:
+.cblk
+\ @(define pair (a b))
+ @a @b
+ @(end)
+ @(pair same same)
+.cble
+.IP data:
+.cblk
+\ one two
+.cble
+.IP result:
+.cblk
+\ [query fails]
+.cble
+.PP
- Query: @(define pair (a b))
- @a @b
- @(end)
- @(pair same same)
-
- Data: one two
-
- Output: [query fails, prints "false"]
-
+Here the query fails because
+.code a
+and
+.code b
+are effectively proxies for the same unbound variable
+.code same
+and are bound to different values, creating a conflict which
+constitutes a match failure.
-.SS Vertical Versus Horizontal Calls
+.SS* Vertical Versus Horizontal Calls
A function call which is the only element of the query line in
which it occurs is ambiguous. It can go either to a vertical
@@ -3703,14 +6232,19 @@ function or to the horizontal one. If both are defined, then
it goes to the vertical one.
Example:
-
- Query: @(define which (x))@(bind x "horizontal")@(end)
- @(define which (x))
- @(bind x "vertical")
- @(end)
- @(which fun)
-
- Output (-B): fun="vertical"
+.IP code:
+.cblk
+\ @(define which (x))@(bind x "horizontal")@(end)
+ @(define which (x))
+ @(bind x "vertical")
+ @(end)
+ @(which fun)
+.cble
+.IP result:
+.cblk
+\ fun="vertical"
+.cble
+.PP
Not only does this call go to the vertical function, but
it is in a vertical context.
@@ -3721,29 +6255,49 @@ horizontal character-matching context, which requires a line of input which can
be traversed:
Example:
+.IP code:
+.cblk
+\ @(define which (x))@(bind x "horizontal")@(end)
+ @(which fun)
+.cble
+.IP data:
+.cblk
+\ ABC
+.cble
+.IP result:
+.cblk
+\ [query fails]
+.cble
+.PP
- Query: @(define which (x))@(bind x "horizontal")@(end)
- @(which fun)
-
- Data: ABC
-
- Output (-B): false
-
-The query failed. Why? Because since @(which fun) is in horizontal mode,
+The query fails because since
+.code @(which fun)
+is in horizontal mode,
it matches characters in a line. Since the function body consists
-of @(bind ...) which doesn't match any characters, the function
-call requires an empty line to match. The line ABC is not empty,
+only of
+.code @(bind ...)
+which doesn't match any characters, the function
+call requires an empty line to match. The line
+.code ABC
+is not empty,
and so there is a matching failure. The following
example corrects this:
Example:
-
- Query: @(define which (x))@(bind x "horizontal")@(end)
- @(which fun)
-
- Data: <empty line>
-
- Output (-B): fun="horizontal"
+.IP code:
+.cblk
+\ @(define which (x))@(bind x "horizontal")@(end)
+ @(which fun)
+.cble
+.IP data:
+.cblk
+\ [empty line]
+.cble
+.IP result:
+.cblk
+\ fun="horizontal"
+.cble
+.PP
A call made in a clearly horizontal context will prefer the
horizontal function, and only fall back on the vertical one
@@ -3757,29 +6311,40 @@ placing it in a horizontal context. Leading material will
do the same thing:
Example:
+.IP code:
+.cblk
+\ @(define which (x))@(bind x "horizontal")@(end)
+ @(define which (x))
+ @(bind x "vertical")
+ @(end)
+ @(which fun)B
+.cble
+.IP data:
+.cblk
+\ B
+.cble
+.IP result:
+.cblk
+\ fun="horizontal"
+.cble
+.PP
- Query: @(define which (x))@(bind x "horizontal")@(end)
- @(define which (x))
- @(bind x "vertical")
- @(end)
- @(which fun)B
-
- Data: B
-
- Output (-B): fun="horizontal"
-
-.SS Local Variables
+.SS* Local Variables
As described earlier, variables bound in a function body which are not
parameters of the function are discarded when the function returns. However,
that, by itself, doesn't make these variables local, because pattern functions
-have visibility to all variables in their calling environment. If a variable x
+have visibility to all variables in their calling environment. If a variable
+.code x
exists already when a function is called, then an attempt to bind it inside a
-function may result in a failure. The @(local) directive must be used in a
+function may result in a failure. The
+.code local
+directive must be used in a
pattern function to list which variables are local.
Example:
+.cblk
@(define path (path))@\e
@(local x y)@\e
@(cases)@\e
@@ -3792,21 +6357,38 @@ Example:
@(bind path "")@\e
@(end)@\e
@(end)
+.cble
This is a horizontal function which matches a path, which lands into four
recursive cases. A path can be parenthesized path followed by a path; it can be
a certain character followed by a path, or it can be empty
-This function ensures that the variables it uses internally, x and y,
-do not have anything to do with any inherited bindings for x and y.
-
-Note that the function is recursive, which cannot work without x and y being
-local, even if no such bindings exist prior to the top-level invocation of the
-function. The invocation @(path x) causes x to be bound, which is
-visible inside the invocation @(path y), but that invocation needs
-to have its own binding of x for local use.
-
-.SS Nested Functions
+This function ensures that the variables it uses internally,
+.code x
+and
+.codn y ,
+do not have anything to do with any inherited bindings for
+.code x
+and
+.codn y .
+
+Note that the function is recursive, which cannot work without
+.code x
+and
+.code y
+being local, even if no such bindings exist prior to the top-level invocation of the
+function. The invocation
+.code @(path x)
+causes
+.code x
+to be bound, which is
+visible inside the invocation
+.codn "@(path y)" ,
+but that invocation needs to have its own binding of
+.code x
+for local use.
+
+.SS* Nested Functions
Function definitions may appear in a function. Such definitions
are visible in all functions which are invoked from the body
@@ -3817,52 +6399,90 @@ calls that take place in a callee, by defining local functions
which capture the references.
Example:
+.IP code:
+.cblk
+\ @(define which)
+ @ (fun)
+ @(end)
+ @(define fun)
+ @ (output)
+ toplevel fun!
+ @ (end)
+ @(end)
+ @(define callee)
+ @ (define fun)
+ @ (output)
+ local fun!
+ @ (end)
+ @ (end)
+ @ (which)
+ @(end)
+ @(callee)
+ @(which)
+.cble
+.IP output:
+.cblk
+\ local fun!
+ toplevel fun!
+.cble
+.PP
- Query: @(define which)
- @ (fun)
- @(end)
- @(define fun)
- @ (output)
- toplevel fun!
- @ (end)
- @(end)
- @(define callee)
- @ (define fun)
- @ (output)
- local fun!
- @ (end)
- @ (end)
- @ (which)
- @(end)
- @(callee)
- @(which)
-
- Output: local fun!
- toplevel fun!
-
-Here, the function "which" is defined which calls "fun".
-A toplevel definition of "fun" is introduced which
-outputs "toplevel fun!". The function "callee" provides its own local
-definition of "fun" which outputs "local fun!" before calling "which". When
-callee is invoked, it calls @(which), whose @(fun) call is routed to callee's
-local definition. When @(which) is called directly from the top level, its
-@(fun) call goes to the toplevel definition.
-
-.SH MODULARIZATION
-
-.SS The Load Directive
-
-The syntax of the load directive is:
-
- @(load EXPR)
-
-Where EXPR evaluates to a string giving the path of the file to load.
+Here, the function
+.code which
+is defined which calls
+.codn fun .
+A toplevel definition of
+.code fun
+is introduced which
+outputs
+.strn "toplevel fun!" .
+The function
+.code callee
+provides its own local
+definition of
+.code fun
+which outputs
+.str "local fun!"
+before calling
+.codn which .
+When
+.code callee
+is invoked, it calls
+.codn which ,
+whose
+.code @(fun)
+call is routed to callee's
+local definition. When
+.code which
+is called directly from the top level, its
+.code fun
+call goes to the toplevel definition.
+
+.SH* MODULARIZATION
+
+.dir load
+
+The syntax of the
+.code load
+directive is:
+
+.cblk
+.mets @(load << expr )
+.cble
+
+Where
+.meta expr
+evaluates to a string giving the path of the file to load.
Unless the path is absolute, it is interpreted relative to the directory of the
-source file from which the @(load) form was read. If there was no such
+source file from which the
+.code @(load)
+syntax was read. If there was no such
source file (for instance, the script was read from standard input),
then it is resolved relative to the current working directory.
-If the file cannot be opened, then the .txr suffix is added and another
+If the file cannot be opened, then the
+.code .txr
+suffix is added and another
attempt is made. Thus load expressions need not refer to the suffix.
In the future, additional suffixes may be searched (compiled versions
of a file).
@@ -3871,124 +6491,163 @@ Loading is performed at evaluation time; it is not a source file inclusion
mechanism. A TXR script is read from beginning to end and parsed prior to
being evaluated.
-See also: the *self-path* variable in TXR Lisp.
+See also: the
+.code *self-path*
+variable in TXR Lisp.
-.SH OUTPUT
+.SH* OUTPUT
-.SS Introduction
+.SS* Introduction
A
.B TXR
-query may perform custom output. Output is performed by @(output) clauses,
+query may perform custom output. Output is performed by
+.code output
+clauses,
which may be embedded anywhere in the query, or placed at the end. Output
occurs as a side effect of producing a part of a query which contains an
-@(output) directive, and is executed even if that part of the query ultimately
+.code @(output)
+directive, and is executed even if that part of the query ultimately
fails to find a match. Thus output can be useful for debugging.
-An output clause specifies that its output goes to a file, pipe, or (by
+An
+.code output
+clause specifies that its output goes to a file, pipe, or (by
default) standard output. If any output clause is executed whose destination is
standard output,
.B TXR
makes a note of this, and later, just prior to termination, suppresses the
usual printing of the variable bindings or the word false.
-.SS The Output Directive
+.dir output
-The syntax of the @(output) directive is:
+The syntax of the
+.code @(output)
+directive is:
- @(output [ <destination> ] { bool-keyword | keyword value }* )
+.cblk
+.mets @(output [ < destination ] { < bool-keyword | < keyword < value }* )
.
. one or more output directives or lines
.
@(end)
+.cble
-The optional destination is a filename, the special name, - which
-redirects to standard output, or a shell command preceded by the ! symbol.
-In the first form, the destination may be specified as a variable
-which holds text, a string literal or a quasiliteral
+The optional
+.meta destination
+is a string which gives the path name of
+a file to open for output. If the name is
+.code -
+it instead denotes standard output, and if it begins with
+.code !
+then the rest of the shell is treated as a shell command
+to which the output is piped.
+
+The destination may be specified as a variable
+which holds text, as a string literal or as a quasiliteral
The keyword list consists of a mixture of boolean keywords which
do not have an argument, or keywords with arguments.
The following boolean keywords are supported:
-.IP :nothrow
-
+.coIP :nothrow
The output directive throws an exception if the output destination
-cannot be opened, unless the :nothrow keyword is present, in which
-case the situation is treated as a match failure.
+cannot be opened, unless the
+.code :nothrow
+keyword is present, in which
+case the situation is treated as a match failure.
Note that since command pipes are processes that report errors
asynchronously, a failing command will not throw an immediate exception that
-can be suppressed with :nothrow. This is for synchronous errors, like
+can be suppressed with
+.codn :nothrow .
+This is for synchronous errors, like
trying to open a destination file, but not having permissions, etc.
-.IP :append
-
+.coIP :append
This keyword is meaningful for files, specifying append mode: the output is to
be added to the end of the file rather than overwriting the file.
-The following value keywords are supported:
-
-.IP :filter
+The following value keywords are supported by
+.codn :append :
+.coIP :filter
The argument can be a symbol, which specifies a filter to be applied to
-the variable substitutions occurring within the output clause.
+the variable substitutions occurring within the
+.code output
+clause.
The argument can also be a list of filter symbols, which specifies
that multiple filters are to be applied, in left to right order.
See the later sections Output Filtering below, and The Deffilter Directive.
-.IP :into
-
-The argument of :into is a symbol which denotes a variable.
+.coIP :into
+The argument of
+.code :into
+is a symbol which denotes a variable.
The output will go into that variable. If the variable is unbound,
it will be created. Otherwise, its contents are overwritten
-unless the :append keyword is used. If :append is used, then
+unless the
+.code :append
+keyword is used. If
+.code :append
+is used, then
the new content will be appended to the previous content of
the variable, after flattening the content to a list,
-as if by the @(flatten) directive.
-
-.IP :named
-
-The argument of :named is a symbol which denotes a variable.
+as if by the
+.code flatten
+directive.
+
+.coIP :named
+The argument of
+.code :named
+is a symbol which denotes a variable.
The file or pipe stream which is opened for the output is
stored in this variable, and is not closed at the end of the
output block. This allows a subsequent output block to continue
output on the same stream, which is possible using the
-next two keywords, :continue or :finish.
+next two keywords,
+.code :continue
+or
+.codn :finish .
A new binding is established for the variable, even if it
already has an existing binding.
-.IP :continue
-
-A destination should not be specified if :continue is used. The argument of
-:continue is an expression, such as a variable name, that must evaluates to a
+.coIP :continue
+A destination should not be specified if
+.code :continue
+is used. The argument of
+.code :continue
+is an expression, such as a variable name, that evaluates to a
stream object. That stream object is used for the output block.
At the end of the output block, the stream is flushed, but not
closed. A usage example is given in the documentation for the Close Directive
below.
-.IP :finish
-
-A destination should not be specified if :finish is used. The argument of
-:finish is an expression, such as a variable name, that must evaluates to a
+.coIP :finish
+A destination should not be specified if
+.code :finish
+is used. The argument of
+.code :finish
+is an expression, such as a variable name, that evaluates to a
stream object. That stream object is used for the output block.
At the end of the output block, the stream is closed.
An example is given in the documentation for the Close Directive
below.
-.SS Output Text
+.SS* Output Text
Text in an output clause is not matched against anything, but is output
verbatim to the destination file, device or command pipe.
-.SS Output Variables
+.SS* Output Variables
-Variables occurring in an output clause do not match anything, but instead
+Variables occurring in an output clause do not match anything; instead
their contents are output.
A variable being output can be any object. If it is of a type other
-than a string, it will be converted to a string as if by the tostring
+than a list or string, it will be converted to a string as if by the
+.code tostring
function in TXR Lisp.
A list is converted to a string in a special way: the elements are
@@ -3996,24 +6655,39 @@ individually converted to a string and then they are catenated together.
The default separator string is a single space: an alternate separation
can be specified as an argument in the brace substitution syntax.
-Lists may be output within @(repeat) or @(rep) clauses. Each nesting of
+Lists may be output within
+.code @(repeat)
+or
+.code @(rep)
+clauses. Each nesting of
these constructs removes one level of nesting from the list variables
that it contains.
-In an output clause, the @{NAME NUMBER} variable syntax generates fixed-width
+In an output clause, the
+.cblk
+.meti >> @{ name << number }
+.cble
+variable syntax generates fixed-width
field, which contains the variable's text. The absolute value of the
-number specifies the field width. For instance -20 and 20 both specify a field
+number specifies the field width. For instance
+.code -20
+and
+.code 20
+both specify a field
width of twenty. If the text is longer than the field, then it overflows the
field. If the text is shorter than the field, then it is left-adjusted within
that field, if the width is specified as a positive number, and right-adjusted
if the width is specified as negative.
An output variable may specify a filter which overrides any filter established
-for the output clause. The syntax for this is @{NAME :filter <filterspec>}.
+for the output clause. The syntax for this is
+.cblk
+.meti @{NAME :filter << filterspec }.
+.cble
The filter specification syntax is the same as in the output clause.
See Output Filtering below.
-.SS Output Variables: Indexing
+.SS* Output Variables: Indexing
Additional syntax is supported in output variables that does not appear
in pattern matching variables.
@@ -4023,16 +6697,16 @@ ranges from a variable, which works with strings, vectors and lists. Elements
are indexed from zero. This notation is only available in brace-enclosed
syntax, and looks like this:
-.IP
-@{NAME[expr]}
-
-Extract the element at the position given by expr.
+.meIP <> @{name[ expr ]}
+Extract the element at the position given by
+.metn expr .
-.IP
-@{NAME[expr1..expr2]}
-
-Extract a range of elements from the position given by expr1, up to
-one position less than the position given by expr2.
+.meIP <> @{name[ expr1..expr2 ]}
+Extract a range of elements from the position given by
+.metn expr1 ,
+up to
+one position less than the position given by
+.metn expr2 .
If the variable is a list, it is treated as a list substitution,
exactly as if it were the value of an unsubscripted list variable.
@@ -4042,40 +6716,65 @@ a single space.
An alternate character may be given as a string argument in the brace
notation.
+.PP
-.TP
Example:
+.cblk
@(bind a ("a" "b" "c" "d"))
@(output)
@{a[1..3] "," 10}
@(end)
-
-The above produces the text "b,c" in a field 10 spaces wide. The [1..3]
-argument extracts a range of a; the "," argument specifies an alternate
-separator string, and 10 specifies the field width.
-
-.SS Output Substitutions
-
-The brace syntax has another syntactic and semantic extension. In place
+.cble
+
+The above produces the text
+.str b,c
+in a field
+.code 10
+spaces wide. The
+.code [1..3]
+argument extracts a range of
+.codn a ;
+the
+.str ","
+argument specifies an alternate
+separator string, and
+.code 10
+specifies the field width.
+
+.SS* Output Substitutions
+
+The brace syntax has another syntactic and semantic extension in
+.code output
+clauses. In place
of the symbol, an expression may appear. The value of that expression
is substituted.
Example:
+.cblk
@(bind a "foo")
@(output)
@{`@a:` -10}
+.cble
-Here, the quasiliteral expression `@a:` is evaluated, producing the string
-"foo:". This string is printed right-adjusted in a 10 character field.
+Here, the quasiliteral expression
+.code `@a:`
+is evaluated, producing the string
+.strn foo: .
+This string is printed right-adjusted in a
+.code 10
+character field.
-.SS The Repeat Directive
+.dir repeat
-The repeat directive generates repeated text from a ``boilerplate'',
+The
+.code repeat
+directive generates repeated text from a "boilerplate",
by taking successive elements from lists. The syntax of repeat is
like this:
+.cblk
@(repeat)
.
.
@@ -4086,120 +6785,194 @@ like this:
.
.
@(end)
+.cble
-Repeat has four types of special clauses, any of which may be
+.code repeat
+has four types of special clauses, any of which may be
specified with empty contents, or omitted entirely. They are described
below.
-Repeat takes arguments, also described below.
+.code repeat
+takes arguments, also described below.
All of the material in the main clause and optional clauses
is examined for the presence of variables. If none of the variables
hold lists which contain at least one item, then no output is performed,
-(unless the repeat specifies an @(empty) clause, see below).
+(unless the repeat specifies an
+.code @(empty)
+clause, see below).
Otherwise, among those variables which contain non-empty lists, repeat finds
the length of the longest list. This length of this list determines the number
of repetitions, R.
-If the repeat contains only a main clause, then the lines of this clause is
+If the
+.code repeat
+contains only a main clause, then the lines of this clause is
output R times. Over the first repetition, all of the variables which, outside
of the repeat, contain lists are locally rebound to just their first item. Over
the second repetition, all of the list variables are bound to their second
item, and so forth. Any variables which hold shorter lists than the longest
list eventually end up with empty values over some repetitions.
-Example: if the list A holds "1", "2" and "3"; the list B holds "A", "B";
-and the variable C holds "X", then
-
+Example: if the list
+.code A
+holds
+.strn 1 ,
+.str 2
+and
+.strn 3 ;
+the list
+.code B
+holds
+.strn A ,
+.strn B ;
+and the variable
+.code C
+holds
+.strn X ,
+then
+
+.cblk
@(repeat)
>> @C
>> @A @B
@(end)
+.cble
will produce three repetitions (since there are two lists, the longest
of which has three items). The output is:
+.cblk
>> X
>> 1 A
>> X
>> 2 B
>> X
>> 3
-
-The last line has a trailing space, since it is produced by "@A @B",
-where @B has an empty value. Since C is not a list variable, it
+.cble
+
+The last line has a trailing space, since it is produced by
+.strn "@A @B" ,
+where
+.code B
+has an empty value. Since
+.code C
+is not a list variable, it
produces the same value in each repetition.
The special clauses are:
-.IP @(single)
-If the repeat produces exactly one repetition, then the contents of this clause
+.coIP @(single)
+If the
+.code repeat
+produces exactly one repetition, then the contents of this clause
are processed for that one and only repetition, instead of the main clause
or any other clause which would otherwise be processed.
-.IP @(first)
+.coIP @(first)
The body of this clause specifies an alternative body to be used for the first
repetition, instead of the material from the main clause.
-.IP @(last)
+.coIP @(last)
The body of this clause is used instead of the main clause for the last
repetition.
-.IP @(empty)
+.coIP @(empty)
If the repeat produces no repetitions, then the body of this clause is output.
If this clause is absent or empty, the repeat produces no output.
-.IP "@(mod n m)"
-The forms n and m are expressions that evaluate to integers. The value of
-m should be nonzero. The clause denoted this way is active if the repetition
-modulo m is equal to n. The first repetition is numbered zero.
-For instance the clause headed by @(mod 0 2) will be used on repetitions
-0, 2, 4, 6, ... and @(mod 1 2) will be used on repetitions 1, 3, 5, 7, ...
-
-.IP "@(modlast n m)"
-The meaning of n and m is the same as in @(mod n m), but one more condition
-is imposed. This clause is used if the repetition modulo m is
-equal to n, and if it is the last repetition.
-
+.coIP "@(mod n m)"
+The forms
+.code n
+and
+.code m
+are expressions that evaluate to integers. The value of
+.code m
+should be nonzero. The clause denoted this way is active if the repetition
+modulo
+.code m
+is equal to
+.codn n .
+The first repetition is numbered zero.
+For instance the clause headed by
+.code @(mod 0 2)
+will be used on repetitions
+0, 2, 4, 6, ... and
+.code @(mod 1 2)
+will be used on repetitions 1, 3, 5, 7, ...
+
+.coIP "@(modlast n m)"
+The meaning of
+.code n
+and
+.code m
+is the same as in
+.codn "@(mod n m)" ,
+but one more condition
+is imposed. This clause is used if the repetition modulo
+.code m
+is equal to
+.codn n ,
+and if it is the last repetition.
.PP
+
The precedence among the clauses which take an iteration is:
-single > first > mod > modlast > last > main. That is if two or more of these
+.codn "single > first > mod > modlast > last > main" .
+That is if two or more of these
clauses can apply to a repetition, then the leftmost one in this precedence
list applies. For instance, if there is just a single repetition, then any of
these special clause types can apply to that repetition, since it is the only
repetition, as well as the first and last one. In this situation, if there is a
-@(single) clause present, then the repetition is processed using that clause.
-Otherwise, if there is a @(first) clause present, that clause is used. Failing
-that, @(mod) is used if there is such a clause and its numeric conditions
-are satisfied. If not then @(modlast) clauses are considered, and if there
-are none, or none of them activate, then @(last) is considered. If none
-of those clauses are present or apply, then the repetition is processed
+.code @(single)
+clause present, then the repetition is processed using that clause.
+Otherwise, if there is a
+.code @(first)
+clause present, that clause is used. Failing
+that,
+.code @(mod)
+is used if there is such a clause and its numeric conditions
+are satisfied. If there isn't, then
+.code @(modlast)
+clauses are considered, and if there
+are none, or none of them activate, then
+.code @(last)
+is considered. Finally if none
+of all these clauses are present or apply, then the repetition is processed
using the main clause.
Repeat supports arguments.
- @(repeat [:counter <symbol>] [:vars (<symbol>*)])
+.cblk
+.mets @(repeat [:counter << symbol ] [:vars <> ( symbol *)])
+.cble
-The :counter argument designates a symbol which will behave as an integer
+The
+.code :counter
+argument designates a symbol which will behave as an integer
variable over the scope of the clauses inside the repeat. The variable provides
access to the repetition count, starting at zero, incrementing with each
repetition.
-The :vars argument specifies a list of variables. The repeat directive
+The
+.code :vars
+argument specifies a list of variables. The repeat directive
will pick out from this list those variables which have bindings.
It will assume that all these variables occur in the repeat block and
-are to be iterated. This syntax is needed for situations in which @(repeat)
-is not able to deduce the existence of a variable in the block.
+are to be iterated. This syntax is needed for situations in which
+.code @(repeat)
+is not able to deduce the existence of a variable in the block.
It does not dig very deeply to discover variables, and does not "see"
variables that are referenced via embedded TXR Lisp expressions.
For instance, the following produces no output:
+.cblk
@(bind list ("a" "b" "c"))
@(output)
@(repeat)
@(format nil "<~a>" list)
@(end)
@(end)
+.cble
Although the list variable appears in the repeat block, it is embedded
in a TXR Lisp construct. That construct will never be evaluated because
@@ -4207,94 +6980,178 @@ no repetitions take place: the repeat construct doesn't find any variables
and so doesn't iterate. The remedy is to provide a little help via
the :vars parameter:
+.cblk
@(bind list ("a" "b" "c"))
@(output)
@(repeat :vars (list))
@(format nil "<~a>" list)
@(end)
@(end)
+.cble
Now the repeat block iterates over list and the output is:
+.cblk
<a>
<b>
<c>
+.cble
-.SS Nested Repeats
+.coSS Nested @ repeat directives
-If a repeat clause encloses variables which hold multidimensional lists,
+If a
+.code repeat
+clause encloses variables which hold multidimensional lists,
those lists require additional nesting levels of repeat (or rep).
It is an error to attempt to output a list variable which has not been
decimated into primary elements via a repeat construct.
-Suppose that a variable X is two-dimensional (contains a list of lists). X
-must be twice nested in a repeat. The outer repeat will walk over the lists
-contained in X. The inner repeat will walk over the elements of each of these
+Suppose that a variable
+.code X
+is two-dimensional (contains a list of lists).
+.code X
+must be twice nested in a
+.codn repeat .
+The outer repeat will traverse the lists
+contained in
+.codn X .
+The inner repeat will traverse the elements of each of these
lists.
A nested repeat may be embedded in any of the clauses of a repeat,
not only the main clause.
-.SS The Rep Directive
-
-The @(rep) directive is similar to @(repeat), but whereas @(repeat) is line
-oriented, @(rep) generates material within a line. It has all the same clauses,
+.dir rep
+
+The
+.code rep
+directive is similar to
+.codn repeat .
+Whereas
+.code repeat
+is line oriented,
+.code rep
+generates material within a line. It has all the same clauses,
but everything is specified within one line:
+.cblk
@(rep)... main material ... .... special clauses ...@(end)
+.cble
-More than one @(rep) can occur within a line, mixed with other material.
-A @(rep) can be nested within a @(repeat) or within another @(rep).
-
-Also, @(rep) accepts the same :counter and :vars arguments.
-
-.SS Repeat and Rep Examples
-
-Example 1: show the list L in parentheses, with spaces between
-the elements, or the symbol NIL if the list is empty:
-
+More than one
+.code @(rep)
+can occur within a line, mixed with other material.
+A
+.code @(rep)
+can be nested within a
+.code @(repeat)
+or within another
+.codn @(rep) .
+
+Also,
+.code @(rep)
+accepts the same
+.code :counter
+and
+.code :vars
+arguments.
+
+.coSS @ repeat and @ rep Examples
+
+Example 1: show the list
+.code L
+in parentheses, with spaces between
+the elements, or the word
+.code EMPTY
+if the list is empty:
+
+.cblk
@(output)
- @(rep)@L @(single)(@L)@(first)(@L @(last)@L)@(empty)NIL@(end)
+ @(rep)@L @(single)(@L)@(first)(@L @(last)@L)@(empty)EMPTY@(end)
@(end)
-
-Here, the @(empty) clause specifies NIL. So if there are no repetitions,
-the text NIL is produced. If there is a single item in the list L,
-then @(single)(@L) produces that item between parentheses. Otherwise
+.cble
+
+Here, the
+.code @(empty)
+clause specifies
+.codn EMPTY .
+So if there are no repetitions,
+the text
+.code EMPTY
+is produced. If there is a single item in the list
+.codn L ,
+then
+.code @(single)(@L)
+produces that item between parentheses. Otherwise
if there are two or more items, the first item is produced with
-a leading parenthesis followed by a space by @(first)(@L , and
-the last item is produced with a closing parenthesis: @(last)@L).
+a leading parenthesis followed by a space by
+.code @(first)(@L
+and the last item is produced with a closing parenthesis:
+.codn @(last)@L) .
All items in between are emitted with a trailing space by
-the main clause: @(rep)@L .
+the main clause:
+.codn @(rep)@L .
-Example 2: show the list L like Example 1 above, but the empty list is ().
+Example 2: show the list L like Example 1 above, but the empty list is
+.codn () .
+.cblk
@(output)
(@(rep)@L @(last)@L@(end))
@(end)
+.cble
This is simpler. The parentheses are part of the text which
-surrounds the @(rep) construct, produced unconditionally.
-If the list L is empty, then @(rep) produces no output, resulting in ().
-If the list L has one or more items, then they are produced with
+surrounds the
+.code @(rep)
+construct, produced unconditionally.
+If the list
+.code L
+is empty, then
+.code @(rep)
+produces no output, resulting in
+.codn () .
+If the list
+.code L
+has one or more items, then they are produced with
spaces each one, except the last which has no space.
-If the list has exactly one item, then the @(last) applies to it
+If the list has exactly one item, then the
+.code @(last)
+applies to it
instead of the main clause: it is produced with no trailing space.
-.SS The Close Directive
-
-The syntax of the @(close) directive is:
-
- @(close <expr>)
-
-Where <expr> evaluates to a stream. The close directive can be
-used to explicitly close streams created using @(output ... :named <var>)
-syntax, as an alternative to the @(output :finish <expr>)
+.dir close
+
+The syntax of the
+.code close
+directive is:
+
+.cblk
+.mets @(close << expr)
+.cble
+
+Where
+.meta expr
+evaluates to a stream. The
+.code close
+directive can be
+used to explicitly close streams created using
+.cblk
+.meti @(output ... :named << var )
+.cble
+syntax, as an alternative to
+.cblk
+.meti @(output :finish << expr ).
+.cble
Examples:
-Write two lines to "foo.txt" over two output blocks using
+Write two lines to
+.str foo.txt
+over two output blocks using
a single stream:
+.cblk
@(output "foo.txt" :named foo)
Hello,
@(end)
@@ -4302,23 +7159,36 @@ a single stream:
world!
@(end)
@(close foo)
+.cble
-The same as above, using :finish rather than :continue
+The same as above, using
+.code :finish
+rather than
+.code :continue
so that the stream is closed at the end of the second block:
+.cblk
@(output "foo.txt" :named foo)
Hello,
@(end)
@(output :finish foo)
world!
@(end)
+.cble
-.SS Output Filtering
+.SS* Output Filtering
Often it is necessary to transform the output to preserve its meaning
under the convention of a given data format. For instance, if a piece of
-text contains the characters < or >, then if that text is being
-substituted into HTML, these should be replaced by &lt; and &gt;.
+text contains the characters
+.code <
+or
+.codn > ,
+then if that text is being
+substituted into HTML, these should be replaced by
+.code &lt;
+and
+.codn &gt; .
This is what filtering is for. Filtering is applied to the contents of output
variables, not to any template text.
.B TXR
@@ -4326,116 +7196,182 @@ implements named filters. Built-in filters are named by keywords,
given below. User-defined filters are possible, however. See notes on the
deffilter directive below.
-Instead of a filter name, the syntax (fun NAME) can be used. This
-denotes that the function called NAME is to be used as a filter.
+Instead of a filter name, the syntax
+.cblk
+.meti (fun << name )
+.cble
+can be used. This
+denotes that the function called
+.meta name
+is to be used as a filter.
This is discussed in the next section Function Filters below.
Built-in filters named by keywords:
-.IP :to_html
+.coIP :to_html
Filter text to HTML, representing special characters using HTML
-ampersand sequences. For instance '>' is replaced by '&gt;'.
+ampersand sequences. For instance
+.code >
+is replaced by
+.codn &gt; .
-.IP :from_html
+.coIP :from_html
Filter text with HTML codes into text in which the codes are replaced by the
-corresponding characters. For instance '&gt;' is replaced by '>'.
+corresponding characters. For instance
+.code &gt;
+is replaced by
+.codn > .
-.IP :upcase
+.coIP :upcase
Convert the 26 lower case letters of the English alphabet to upper case.
-.IP :downcase
+.coIP :downcase
Convert the 26 upper case letters of the English alphabet to lower case.
-.IP :frompercent
+.coIP :frompercent
Decode percent-encoded text. Character triplets consisting
-of the % character followed by a pair of hexadecimal digits (case insensitive)
+of the
+.code %
+character followed by a pair of hexadecimal digits (case insensitive)
are are converted to bytes having the value represented by the hexadecimal
digits (most significant nybble first). Sequences of one or more such bytes are
treated as UTF-8 data and decoded to characters.
-.IP :topercent
+.coIP :topercent
Convert to percent encoding according to RFC 3986. The text is first converted
to UTF-8 bytes. The bytes are then converted back to text as follows.
Bytes in the range 0 to 32, and 127 to 255 (note: including the ASCII DEL),
bytes whose values correspond to ASCII characters which are listed by RFC 3986
as being in the "reserved set", and the byte value corresponding to the
-ASCII % character are encoded as a three-character sequence consisting
-of the % character followed by two hexadecimal digits derived from the
+ASCII
+.code %
+character are encoded as a three-character sequence consisting
+of the
+.code %
+character followed by two hexadecimal digits derived from the
byte value (most significant nybble first, upper case). All other bytes
are converted directly to characters of the same value without any such
encoding.
-.IP :fromurl
+.coIP :fromurl
Decode from URL encoding, which is like percent encoding, except that
-if the unencoded + character occurs, it is decoded to a space character.
-Of course %20 still decodes to space, and %2B to the + character.
-
-.IP :tourl
+if the unencoded
+.code +
+character occurs, it is decoded to a space character. Of course
+.code %20
+still decodes to space, and
+.code %2B
+to the
+.code +
+character.
+
+.coIP :tourl
Encode to URL encoding, which is like percent encoding except that
-a space maps to + rather than %20. The + character, being in the
-reserved set, encodes to %2B.
-
-.IP :tonumber
-Converts strings to numbers. Strings that contain a period, e or E are
-converted to floating point as if by the function flo-str. Otherwise
-they are converted to integer as if using int-str with a radix of 10.
-Non-numeric junk results in the object nil.
-
-.IP :tointeger
-Converts strings to integers as if using int-str with a radix of 10.
-Non-numeric junk results in the object nil.
-
-.IP :tofloat
-Converts strings to floating-point values as if using the function flo-str.
-Non-numeric junk results in the object nil.
-
-.IP :hextoint
-Converts strings to integers as if using int-str with a radix of 16.
-Non-numeric junk results in the object nil.
+a space maps to
+.code +
+rather than
+.codn %20 .
+The
+.code +
+character, being in the
+reserved set, encodes to
+.codn %2B .
+
+.coIP :tonumber
+Converts strings to numbers. Strings that contain a period,
+.code e
+or
+.code E
+are converted to floating point as if by the Lisp function
+.codn flo-str .
+Otherwise they are converted to integer as if using
+.code int-str
+with a radix of 10.
+Non-numeric junk results in the object
+.codn nil .
+
+.coIP :tointeger
+Converts strings to integers as if using
+.code int-str
+with a radix of 10.
+Non-numeric junk results in the object
+.codn nil .
+
+.coIP :tofloat
+Converts strings to floating-point values as if using the function
+.codn flo-str .
+Non-numeric junk results in the object
+.codn nil.
+
+.coIP :hextoint
+Converts strings to integers as if using
+.code int-str
+with a radix of 16.
+Non-numeric junk results in the object
+.codn nil.
.PP
-.TP
-Examples
+Examples:
To escape HTML characters in all variable substitutions occurring in an
-output clause, specify :filter :to_html in the directive:
+output clause, specify
+.code :filter :to_html
+in the directive:
+.cblk
@(output :filter :to_html)
...
@(end)
+.cble
To filter an individual variable, add the syntax to the variable spec:
+.cblk
@(output)
@{x :filter :to_html}
@(end)
+.cble
Multiple filters can be applied at the same time. For instance:
+.cblk
@(output)
@{x :filter (:upcase :to_html)}
@(end)
+.cble
-This will fold the contents of x to upper case, and then encode any special
+This will fold the contents of
+.code x
+to upper case, and then encode any special
characters into HTML. Beware of combinations that do not make sense.
For instance, suppose the original text is HTML, containing codes
-like '&quot;'. The compound filter (:upcase :from_html) will not work
-because '&quot;' will turn to '&QUOT;' which no longer be recognized
-by the :from_html filter, because the entity names in HTML codes
+like
+.codn &quot; .
+The compound filter
+.code (:upcase :from_html)
+will not work
+because
+.code &quot;
+will turn to
+.code &QUOT;
+which no longer be recognized by the
+.code :from_html
+filter, sonce the entity names in HTML codes
are case-sensitive.
Capture some numeric variables and convert to numbers:
+.cblk
@date @time @temperature @pressure
@(filter :tofloat temperature pressure)
@;; temperature and pressure can now be used in calculations
+.cble
-.SS Function Filters
+.SS* Function Filters
A function can be used as a filter. For this to be possible, the function must
conform to certain rules:
-
.IP 1.
The function must take two special arguments, which may be followed
by additional arguments.
@@ -4448,6 +7384,7 @@ as the final filter in a chain, it must produce a string.
For instance, the following is a valid filter function:
+.cblk
@(define foo_to_bar (in out))
@ (next :string in)
@ (cases)
@@ -4457,120 +7394,180 @@ For instance, the following is a valid filter function:
@ (bind out in)
@ (end)
@(end)
-
-This function binds the out parameter to "bar" if the in parameter
-is "foo", otherwise it binds the out parameter to a copy of the in parameter.
+.cble
+
+This function binds the
+.code out
+parameter to
+.str bar
+if the in parameter
+is
+.strn foo ,
+otherwise it binds the
+.code out
+parameter to a copy of the
+.code in
+parameter.
This is a simple filter.
-To use the filter, use the syntax (:fun foo_to_bar) in place of a filter name.
+To use the filter, use the syntax
+.code (:fun foo_to_bar)
+in place of a filter name.
For instance in the bind directive:
+.cblk
@(bind "foo" "bar" :lfilt (:fun foo_to_bar))
+.cble
-The above should succeed since the left side is filtered from "foo"
-to "bar", so that there is a match.
+The above should succeed since the left side is filtered from
+.str foo
+to
+.strn bar ,
+so that there is a match.
Of course, function filters can be used in a chain:
+.cblk
@(output :filter (:downcase (:fun foo_to_bar) :upcase))
...
@(end)
+.cble
-Here is a split function which takes an extra argument.
+Here is a split function which takes an extra argument
+which specifies the separator:
+.cblk
@(define split (in out sep))
@ (next :list in)
@ (coll)@(maybe)@token@sep@(or)@token@(end)@(end)
@ (bind out token)
@(end)
+.cble
Furthermore, note that it produces a list rather than a string.
This function separates the argument in into tokens according to the
-separator text sep.
+separator text carried in the variable
+.codn sep .
-Here is another function, join, which catenates a list:
+Here is another function,
+.codn join ,
+which catenates a list:
+.cblk
@(define join (in out sep))
@ (output :into out)
@ (rep)@in@sep@(last)@in@(end)
@ (end)
@(end)
+.cble
Now here is these two being used in a chain:
+.cblk
@(bind text "how,are,you")
@(output :filter (:fun split ",") (:fun join "-"))
@text
@(end)
+.cble
Output:
+.cblk
how-are-you
+.cble
When the filter invokes a function, it generates the first two arguments
internally to pass in the input value and capture the output. The remaining
-arguments from the (:fun ...) construct are also passed to the function.
-Thus the "," and "-" are passed as the sep argument to split and join.
-
-Note that split puts out a list, which join accepts. So the overall filter
+arguments from the
+.code (:fun ...)
+construct are also passed to the function.
+Thus the string objects
+.str ","
+and
+.str "-"
+are passed as the
+.code sep
+argument to
+.code split
+and
+.codn join .
+
+Note that
+.code split
+puts out a list, which
+.code join
+accepts. So the overall filter
chain operates on a string: a string goes into split, and a string comes out of
join.
-.SS The Deffilter Directive
+.dir deffilter
-The deffilter directive allows a query to define a custom filter, which
-can then be used in @(output) clauses to transform substituted data.
+The
+.code deffilter
+directive allows a query to define a custom filter, which
+can then be used in
+.code output
+clauses to transform substituted data.
This directive's syntax is illustrated in this example:
+.IP code:
+.cblk
+\ @(deffilter rot13
+ ("a" "n")
+ ("b" "o")
+ ("c" "p")
+ ("d" "q")
+ ("e" "r")
+ ("f" "s")
+ ("g" "t")
+ ("h" "u")
+ ("i" "v")
+ ("j" "w")
+ ("k" "x")
+ ("l" "y")
+ ("m" "z")
+ ("n" "a")
+ ("o" "b")
+ ("p" "c")
+ ("q" "d")
+ ("r" "e")
+ ("s" "f")
+ ("t" "g")
+ ("u" "h")
+ ("v" "i")
+ ("w" "j")
+ ("x" "k")
+ ("y" "l")
+ ("z" "m"))
+ @(collect)
+ @line
+ @(end)
+ @(output :filter rot13)
+ @(repeat)
+ @line
+ @(end)
+ @(end)
+.cble
+.IP data:
+.cblk
+\ hey there!
+.cble
+.IP output:
+.cblk
+\ url gurer!
+.cble
+.PP
- Query: @(deffilter rot13
- ("a" "n")
- ("b" "o")
- ("c" "p")
- ("d" "q")
- ("e" "r")
- ("f" "s")
- ("g" "t")
- ("h" "u")
- ("i" "v")
- ("j" "w")
- ("k" "x")
- ("l" "y")
- ("m" "z")
- ("n" "a")
- ("o" "b")
- ("p" "c")
- ("q" "d")
- ("r" "e")
- ("s" "f")
- ("t" "g")
- ("u" "h")
- ("v" "i")
- ("w" "j")
- ("x" "k")
- ("y" "l")
- ("z" "m"))
- @(collect)
- @line
- @(end)
- @(output :filter rot13)
- @(repeat)
- @line
- @(end)
- @(end)
-
- Input: hey there!
-
- Output: url gurer!
-
-
-The deffilter symbol must be followed by the name of the filter to be defined,
+The
+.code deffilter
+symbol must be followed by the name of the filter to be defined,
followed by forms which evaluate to lists of strings. Each list must
be at least two elements long and specifies one or more texts which are mapped
to a replacement text. For instance, the following specifies a telephone keypad
mapping from upper case letters to digits.
-
- @(deffilter alpha_to_phone ("E" "0")
+
+.cblk
+ @(deffilter alpha_to_phone ("E" "0")
("J" "N" "Q" "1")
("R" "W" "X" "2")
("D" "S" "Y" "3")
@@ -4586,9 +7583,10 @@ mapping from upper case letters to digits.
@(bind x ("from" "to"))
@(bind y ("---" "+++"))
@(deffilter sub x y)
+.cble
-The last deffilter above equivalent to
-@(deffilter sub ("from" "to") ("---" "+++")).
+The last deffilter above equivalent to
+.codn "@(deffilter sub ("from" "to") ("---" "+++"))" .
Filtering works using a longest match algorithm. The input is scanned from left
to right, and the longest piece of text is identified at every character
@@ -4608,22 +7606,33 @@ same left hand string with different right hand translations, the later ones
take precedence. No warning is issued.
-.SS The Filter Directive
+.dir filter
-The syntax of the filter directive is:
+The syntax of the
+.code filter
+directive is:
+.cblk
@(filter FILTER { VAR }+ )
+.cble
A filter is specified, followed by one or more variables whose values
are filtered and stored back into each variable.
-Example: convert a, b, and c to upper case and HTML encode:
+Example: convert
+.codn a ,
+.codn b ,
+and
+.code c
+to upper case and HTML encode:
+.cblk
@(filter (:upcase :to_html) a b c)
+.cble
-.SH EXCEPTIONS
+.SH* EXCEPTIONS
-.SS Introduction
+.SS* Introduction
The exceptions mechanism in
.B TXR
@@ -4639,54 +7648,97 @@ of whose applications is error handling.
An exception control transfer (simply called an exception) is always identified
by a symbol, which is its type. Types are organized in a subtype-supertype
-hierarchy. For instance, the file-error exception type is a subtype of the
-error type. This means that a file error is a kind of error. An exception
-handling block which catches exceptions of type error will catch exceptions of
-type file-error, but a block which catches file-error will not catch all
-exceptions of type error. A query-error is a kind of error, but not a kind of
-file-error. The symbol t is the supertype of every type: every exception type
-is considered to be a kind of t. (Mnemonic: t stands for type, as in any
-type).
-
-Exceptions are handled using @(catch) clauses within a @(try) directive.
-
-In addition to being useful for exception handling, the @(try) directive
-also provides unwind protection by means of a @(finally) clause,
+hierarchy. For instance, the
+.code file-error
+exception type is a subtype of the
+.code error
+type. This means that a file error is a kind of error. An exception
+handling block which catches exceptions of type
+.code error
+will catch exceptions of
+type
+.codn file-error ,
+but a block which catches
+.code file-error
+will not catch all
+exceptions of type
+.codn error .
+A
+.code query-error
+is a kind of error, but not a kind of
+.codn file-error .
+The symbol
+.code t
+is the supertype of every type: every exception type
+is considered to be a kind of
+.codn t .
+(Mnemonic:
+.code t
+stands for type, as in any type).
+
+Exceptions are handled using
+.code @(catch)
+clauses within a
+.code @(try)
+directive.
+
+In addition to being useful for exception handling, the
+.code @(try)
+directive
+also provides unwind protection by means of a
+.code @(finally)
+clause,
which specifies query material to be executed unconditionally when
the try clause terminates, no matter how it terminates.
-.SS The Try Directive
+.dir try
-The general syntax of the try directive is
+The general syntax of the
+.code try
+directive is
+.cblk
@(try)
... main clause, required ...
... optional catch clauses ...
... optional finally clause
@(end)
+.cble
-A catch clause looks like:
+A
+.code catch
+clause looks like:
- @(catch TYPE)
+.cblk
+ @(catch TYPE [ PARAMETERS ])
.
.
.
+.cble
-and also the this form, equivalent to @(catch (t)):
+and also this simple form:
+.cblk
@(catch)
.
.
.
+.cble
-which catches all exceptions.
+which catches all exceptions, and is equivalent
+to
+.codn "@(catch t)" .
-A finally clause looks like:
+A
+.code finally
+clause looks like:
+.cblk
@(finally)
...
.
.
+.cble
The main clause may not be empty, but the catch and finally may be.
@@ -4694,124 +7746,237 @@ A try clause is surrounded by an implicit anonymous block (see BLOCKS section
above). So for instance, the following is a no-op (an operation with no effect,
other than successful execution):
+.cblk
@(try)
@(accept)
@(end)
+.cble
-The @(accept) causes a successful termination of the implicit anonymous block.
+The
+.code @(accept)
+causes a successful termination of the implicit anonymous block.
Execution resumes with query lines or directives which follow, if any.
-Try clauses and blocks interact. For instance, a block accept from within
-a try clause invokes a finally.
-
- Query: @(block foo)
- @ (try)
- @ (accept foo)
- @ (finally)
- @ (output)
- bye!
- @ (end)
- @ (end)
-
- Output: bye!
+.code try
+clauses and blocks interact. For instance, an
+.code accept
+from within
+a try clause invokes a
+.codn finally .
+.IP code:
+.cblk
+\ @(block foo)
+ @ (try)
+ @ (accept foo)
+ @ (finally)
+ @ (output)
+ bye!
+ @ (end)
+ @ (end)
+.cble
+.IP output:
+.cblk
+\ bye!
+.cble
+.PP
-How this works: the try block's main clause is @(accept foo). This causes
-the enclosing block named foo to terminate, as a successful match.
-Since the try is nested within this block, it too must terminate
-in order for the block to terminate. But the try has a finally clause,
+How this works: the
+.code try
+block's main clause is
+.codn "@(accept foo)" .
+This causes
+the enclosing block named
+.code foo
+to terminate, as a successful match.
+Since the
+.cod try
+is nested within this block, it too must terminate
+in order for the block to terminate. But the try has a
+.code finally
+clause,
which executes unconditionally, no matter how the try block
-terminates. The finally clause performs some output, which is seen.
+terminates. The
+.code finally
+clause performs some output, which is seen.
-.SS The Finally Clause
+.coSS The @ finally clause
-A try directive can terminate in one of three ways. The main clause
+A
+.code try
+directive can terminate in one of three ways. The main clause
may match successfully, and possibly yield some new variable bindings.
The main clause may fail to match. Or the main clause may be terminated
by a non-local control transfer, like an exception being thrown or a block
return (like the block foo example in the previous section).
-No matter how the try clause terminates, the finally clause is processed.
-
-Now, the finally clause is itself a query which binds variables, which leads to
-the question: what happens to such variables? What if the finally block fails
-as a query? Another question is: what if a finally clause itself initiates a
+No matter how the
+.code try
+clause terminates, the
+.code finally
+clause is processed.
+
+The
+.code finally
+clause is itself a query which binds variables, which leads to
+questions: what happens to such variables? What if the
+.code finally
+block fails
+as a query? As well as: what if a
+.code finally
+clause itself initiates a
control transfer? Answers follow.
-Firstly, a finally clause will contribute variable bindings only if the main
+Firstly, a
+.code finally
+clause will contribute variable bindings only if the main
clause terminates normally (either as a successful or failed match).
-If the main clause successfully matches, then the finally block continues
+If the main clause of the
+.code try
+block successfully matches, then the
+.code finally
+block continues
matching at the next position in the data, and contributes bindings.
-If the main clause fails, then the finally block matches at the
-same position.
-
-The overall try directive succeeds as a match if either the main clause
-or the finally clause succeed. If both fail, then the try directive is
-a failed match. The subquery in which it is located fails, et cetera.
+If the main clause fails, then the
+.code finally
+block tries to match at the same position where the main clause failed.
+
+The overall
+.code try
+directive succeeds as a match if either the main clause
+or the
+.code finally
+clause succeed. If both fail, then the try directive is
+a failed match.
Example:
+.IP code:
+.cblk
+\ @(try)
+ @a
+ @(finally)
+ @b
+ @(end)
+ @c
+.cble
+.IP data:
+.cblk
+\ 1
+ 2
+ 3
+.cble
+.IP result:
+.cblk
+\ a="1"
+ b="2"
+ c="3"
+.cble
+.PP
- Query: @(try)
- @a
- @(finally)
- @b
- @(end)
- @c
-
- Data: 1
- 2
- 3
-
- Output (-B): a="1"
- b="2"
- c="3"
-
-In this example, the main clause of the try captures line "1" of the data as
-variable a, then the finally clause captures "2" as b, and then the
-query continues with the @c variable after try block, and captures "3".
-
+In this example, the main clause of the
+.code try
+captures line
+.str 1
+of the data as
+variable
+.codn a ,
+then the finally clause captures
+.str 2
+as
+.codn b ,
+and then the query continues with the
+.code @c
+line after try block, so that
+.code c
+captures
+.strn "3" .
Example:
+.IP code:
+.cblk
+\ @(try)
+ hello @a
+ @(finally)
+ @b
+ @(end)
+ @c
+.cble
+.IP data:
+.cblk
+\ 1
+ 2
+.cble
+.IP result:
+.cblk
+\ b="1"
+ c="2"
+.cble
+.PP
- Query: @(try)
- hello @a
- @(finally)
- @b
- @(end)
- @c
-
- Data: 1
- 2
-
- Output (-B): b=1
- c=2
-
-In this example, the main clause of the try fails to match, because
-the input is not prefixed with "hello ". However, the finally clause
-matches, binding b to "1". This means that the try block is a successful
-match, and so processing continues with @c which captures "2".
-
-When finally clauses are processed during a non-local return,
+In this example, the main clause of the
+.code try
+fails to match, because
+the input is not prefixed with
+.srn "hello " .
+However, the
+.code finally
+clause
+matches, binding
+.code b
+to
+.strn "1" .
+This means that the try block is a successful
+match, and so processing continues with
+.code @c
+which captures
+.strn "2" .
+
+When
+.code finally
+clauses are processed during a non-local return,
they have no externally visible effect if they do not bind variables.
However, their execution makes itself known if they perform side effects,
such as output.
-A finally clause guards only the main clause and the catch clauses. It does not
-guard itself. Once the finally clause is executing, the try block is no
+A
+.code finally
+clause guards only the main clause and the
+.code catch
+clauses. It does not
+guard itself. Once the finally clause is executing, the
+.code try
+block is no
longer guarded. This means if a nonlocal transfer, such as a block accept
or exception, is initiated within the finally clause, it will not re-execute
-the finally clause. The finally clause is simply abandoned.
-
-The disestablishment of blocks and try clauses is properly interleaved
-with the execution of finally clauses. This means that all surrounding
-exit points are visible in a finally clause, even if the finally clause
+the
+.code finally
+clause. The
+.code finally
+clause is simply abandoned.
+
+The disestablishment of blocks and
+.code try
+clauses is properly interleaved
+with the execution of
+.code finally
+clauses. This means that all surrounding
+exit points are visible in a
+.code finally
+clause, even if the
+.code finally
+clause
is being invoked as part of a transfer to a distant exit point.
The finally clause can make a control transfer to an exit point which
is more near than the original one, thereby "hijacking" the control
-transfer. Also, the anonymous block established by the try directive
-is visible in the finally clause.
+transfer. Also, the anonymous block established by the
+.code try
+directive
+is visible in the
+.code finally
+clause.
Example:
+.cblk
@(try)
@ (try)
@ (next "nonexistent-file")
@@ -4823,216 +7988,441 @@ Example:
file error caught
@ (end)
@(end)
+.cble
-In this example, the @(next) directive throws an exception of type file-error,
+In this example, the
+.code @(next)
+directive throws an exception of type
+.codn file-error ,
because the given file does not exist. The exit point for this exception is the
-@(catch file-error) clause in the outer-most try block. The inner block is
+.code @(catch file-error)
+clause in the outer-most
+.code try
+block. The inner block is
not eligible because it contains no catch clauses at all. However, the inner
try block has a finally clause, and so during the processing of this
-exception which is headed for the @(catch file-error), the finally
-clause performs an anonymous accept. The exit point for the accept
-is the anonymous block surrounding the inner try. So the original
-transfer to the catch clause is forgotten. The inner try terminates
-successfully, and since it constitutes the main clause of the outer try,
-that also terminates successfully. The "file error caught" message is
-never printed.
-
-.SS Catch Clauses
-
-Catch clauses establish a try block as a potential exit point for
-an exception-induced control transfer (called a ``throw'').
+exception which is headed for
+.codn "@(catch file-error)" ,
+the
+.code finally
+clause performs an anonymous
+.codn accept .
+The exit point for that
+.code accept
+is the anonymous block
+surrounding the inner
+.codn try .
+So the original
+transfer to the
+.code catch
+clause is thereby abandoned. The inner
+.code try
+terminates
+successfully due to the
+.codn accept ,
+and since it constitutes the main clause of the outer try,
+that also terminates successfully. The
+.str "file error caught"
+message is never printed.
+
+.c1SS catch clauses
+
+.code catch
+clauses establish their associated
+.code try
+blocks as potential exit points for
+exception-induced control transfers (called "throws").
-A catch clause specifies an optional list of symbols which represent
-the exception types which it catches. The catch clause will catch
+A
+.code catch
+clause specifies an optional list of symbols which represent
+the exception types which it catches. The
+.code catch
+clause will catch
exceptions which are a subtype of any one of those exception types.
-If a try block has more than one catch clause which can match a given
+If a
+.code try
+block has more than one
+.code catch
+clause which can match a given
exception, the first one will be invoked.
-When a catch is invoked, it is of course understood that the main clause did
+When a
+.code catch
+is invoked, it is of course understood that the main clause did
not terminate normally, and so the main clause could not have produced any
bindings.
-Catches are processed prior to finally.
+.code catch
+clauses are processed prior to
+.codn finally .
-If a catch clause itself throws an exception, that exception cannot
+If a
+.code catch
+clause itself throws an exception, that exception cannot
be caught by that same clause or its siblings in the same try block.
-The catches of that block are no longer visible at that point.
-Nevertheless, the catch clauses are still protected by the finally block.
-If a catch clause throws, the finally block is still processed.
-
-If a finally block throws an exception, then it is simply aborted;
+The
+.code catch
+clauses of that block are no longer visible at that point.
+Nevertheless, the
+.code catch
+clauses are still protected by the finally block.
+If a catch clause throws, or otherwise terminates, the
+.code finally
+block is still processed.
+
+If a
+.code finally
+block throws an exception, then it is simply aborted;
the remaining directives in that block are not processed.
-So the success or failure of the try block depends on the behavior of the catch
-clause or the finally, if there is one. If either of them succeed, then the try
+So the success or failure of the
+.code try
+block depends on the behavior of the
+.code catch
+clause or the
+.ocde finally
+clause, if there is one. If either of them succeed, then the try
block is considered a successful match.
Example:
+.IP code:
+.cblk
+\ @(try)
+ @ (next "nonexistent-file")
+ @ x
+ @ (catch file-error)
+ @a
+ @(finally)
+ @b
+ @(end)
+ @c
+.cble
+.IP data:
+.cblk
+\ 1
+ 2
+ 3
+.cble
+.IP result:
+.cblk
+\ a="1"
+ b="2"
+ c="3"
+.cble
+.PP
- Query: @(try)
- @ (next "nonexistent-file")
- @ x
- @ (catch file-error)
- @a
- @(finally)
- @b
- @(end)
- @c
-
- Data: 1
- 2
- 3
-
- Output (-B): a="1"
- b="2"
- c="3"
-
-Here, the try block's main clause is terminated abruptly by a file-error
-exception from the @(next) directive. This is handled by the
-catch clause, which binds variable a to the input line "1".
-Then the finally clause executes, binding b to "2". The try block
-then terminates successfully, and so @c takes "3".
-
-.SS Catch Clauses with Parameters
+Here, the
+.code try
+block's main clause is terminated abruptly by a
+.code file-error
+exception from the
+.code @(next)
+directive. This is handled by the
+.code catch
+clause, which binds variable
+.code a
+to the input line
+.strn 1 .
+Then the
+.code finally
+clause executes, binding
+.code b
+to
+.strn 2 .
+The
+.code try
+block then terminates successfully, and so
+.code @c
+takes
+.strn "3" .
+
+.coSS @ catch Clauses with Parameters
-A catch may have parameters following the type name, like this:
+A
+.code catch
+clause may have parameters following the type name, like this:
+.cblk
@(catch pair (a b))
+.cble
To write a catch-all with parameters, explicitly write the
master supertype t:
+.cblk
@(catch t (arg ...))
-
-Parameters are useful in conjunction with throw. The built-in
-error exceptions generate one argument, which is a string containing
-the error message. Using throw, arbitrary parameters can be passed
-from the throw site to the catches.
-
-.SS The Throw Directive
-
-The throw directive generates an exception. A type must be specified,
+.cble
+
+Parameters are useful in conjunction with
+.codn throw .
+The built-in
+.code error
+exceptions carry one argument, which is a string containing
+the error message. Using
+.codn throw ,
+arbitrary parameters can be passed
+from the throw site to the catch site.
+
+.dir throw
+
+The
+.code throw
+directive generates an exception. A type must be specified,
followed by optional arguments. For example,
+.cblk
@(throw pair "a" `@file.txt`)
-
-throws an exception of type pair, with two arguments, being "a"
-and the expansion of the quasiliteral `@file.txt`.
-
-The selection of the target catch is performed purely using the type
+.cble
+
+throws an exception of type
+.codn pair ,
+with two arguments, being
+.str a
+and the expansion of the quasiliteral
+.codn `@file.txt` .
+
+The selection of the target
+.code catch
+is performed purely using the type
name; the parameters are not involved in the selection.
-Binding takes place between the arguments given in throw, and the
-target catch.
+Binding takes place between the arguments given in
+.code throw
+and the target
+.codn catch .
-If any catch parameter, for which a throw argument is given, is a bound
+If any
+.code catch
+parameter, for which a
+.code throw
+argument is given, is a bound
variable, it has to be identical to the argument, otherwise the catch fails.
-(Control still passes to the catch, but the catch is a failed match).
-
- Query: @(bind a "apple")
- @(try)
- @(throw e "banana")
- @(catch e (a))
- @(end)
-
- Output: false
+(Control still passes to the
+.codn catch ,
+but the catch is a failed match).
+
+.IP code:
+.cblk
+\ @(bind a "apple")
+ @(try)
+ @(throw e "banana")
+ @(catch e (a))
+ @(end)
+.cble
+.IP result:
+.cblk
+\ [query fails]
+.cble
+.PP
If any argument is an unbound variable, the corresponding parameter
-in the catch is left alone: if it is an unbound variable, it remains
+in the
+.code catch
+is left alone: if it is an unbound variable, it remains
unbound, and if it is bound, it stays as is.
+.IP code:
+.cblk
+\ @(try)
+ @(trow e "honda" unbound)
+ @(catch e (car1 car2))
+ @car1 @car2
+ @(end)
+.cble
+.IP data:
+.cblk
+\ honda toyota
+.cble
+.IP result:
+.cblk
+\ car1="honda"
+ car2="toyota"
+.cble
+.PP
- Query: @(try)
- @(trow e "honda" unbound)
- @(catch e (car1 car2))
- @car1 @car2
- @(end)
-
- Data: honda toyota
-
- Output (-B): car1="honda"
- car2="toyota"
-
-If a catch has fewer parameters than there are throw arguments,
-the excess arguments are ignored.
-
- Query: @(try)
- @(throw e "banana" "apple" "pear")
- @(catch e (fruit))
- @(end)
-
- Output (-B): fruit="banana"
+If a
+.code catch
+has fewer parameters than there are throw arguments,
+the excess arguments are ignored:
+.IP code:
+.cblk
+\ @(try)
+ @(throw e "banana" "apple" "pear")
+ @(catch e (fruit))
+ @(end)
+.cble
+.IP result:
+.cblk
+\ fruit="banana"
+.cble
+.PP
-If a catch has more parameters than there are throw arguments, the excess
+If a
+.code catch
+has more parameters than there are throw arguments, the excess
parameters are left alone. They may be bound or unbound variables.
+.IP code:
+.cblk
+\ @(try)
+ @(trow e "honda")
+ @(catch e (car1 car2))
+ @car1 @car2
+ @(end)
+.cble
+.IP data:
+.cblk
+\ honda toyota
+.cble
+.IP result:
+.cblk
+\ car1="honda"
+ car2="toyota"
+.cble
+.PP
- Query: @(try)
- @(trow e "honda")
- @(catch e (car1 car2))
- @car1 @car2
- @(end)
-
- Data: honda toyota
-
- Output (-B): car1="honda"
- car2="toyota"
-
-A throw argument passing a value to a catch parameter which is unbound causes
+A
+.code throw
+argument passing a value to a
+.code catch
+parameter which is unbound causes
that parameter to be bound to that value.
-Throw arguments are evaluated in the context of the throw, and the bindings
+.code throw
+arguments are evaluated in the context of the
+.codn throw ,
+and the bindings
which are available there. Consideration of what parameters are bound
is done in the context of the catch.
+.IP code:
+.cblk
+\ @(bind c "c")
+ @(try)
+ @(forget c)
+ @(bind (a c) ("a" "lc"))
+ @(throw e a c)
+ @(catch e (b a))
+ @(end)
+.cble
+.IP result:
+.cblk
+\ c="c"
+ b="a"
+ a="lc"
+.cble
+.PP
- Query: @(bind c "c")
- @(try)
- @(forget c)
- @(bind (a c) ("a" "lc"))
- @(throw e a c)
- @(catch e (b a))
- @(end)
-
- Output (-B): c="c"
- b="a"
- a="lc"
-
-In the above example, c has a toplevel binding to the string "c",
-but is then unbound within the try construct, and rebound to the value "c".
-Since the try construct is terminated by a throw, these modifications of the
+In the above example,
+.code c
+has a toplevel binding to the string
+.strn "c" ,
+but then becomes unbound
+via
+.code forget
+within the
+.code try
+construct, and rebound to the value
+.strn lc .
+Since the
+.code try
+construct is terminated by a
+.codn throw ,
+these modifications of the
binding environment are discarded. Hence, at the end of the query, variable
-c ends up bound to the original value "c". The throw still takes place
-within the scope of the bindings set up by the try clause, so the values of
-a and c that are thrown are "a" and "lc". However, at the catch site, variable
-a does not have a binding. At that point, the binding to "a" established in
-the try has disappeared already. Being unbound, the catch parameter a can take
+.code c
+ends up bound to the original value
+.strn c .
+The
+.code throw
+still takes place
+within the scope of the bindings set up by the
+.code try
+clause, so the values of
+.code a
+and
+.code c
+that are thrown are
+.str a
+and
+.strn lc .
+However, at the
+.code catch
+site, variable
+.code a
+does not have a binding. At that point, the binding to
+.str a
+established in
+the
+.code try
+has disappeared already. Being unbound, the
+.code catch
+parameter
+.code a
+can take
whatever value the corresponding throw argument provides, so it ends up with
-"lc".
+.strn lci .
-.SS The Defex Directive
+.dir defex
-The defex directive allows the query writer to invent custom exception types,
+The
+.code defex
+directive allows the query writer to invent custom exception types,
which are arranged in a type hierarchy (meaning that some exception types are
considered subtypes of other types).
-Subtyping means that if an exception type B is a subtype of A, then every
-exception of type B is also considered to be of type A. So a catch for type A
-will also catch exceptions of type B. Every type is a supertype of itself: an
-A is a kind of A. This of course implies that ever type is a subtype of itself
-also. Furthermore, every type is a subtype of the type t, which has no
-supertype other than itself. Type nil is is a subtype of every type, including
-itself. The subtyping relationship is transitive also. If A is a subtype
-of B, and B is a subtype of C, then A is a subtype of C.
-
-Defex may be invoked with no arguments, in which case it does nothing:
-
+Subtyping means that if an exception type
+.code B
+is a subtype of
+.codn A ,
+then every
+exception of type
+.code B
+is also considered to be of type
+.codn A .
+So a catch for type
+.code A
+will also catch exceptions of type
+.codn B .
+Every type is a supertype of itself: an
+.code A
+is a kind of
+.codn A .
+This of course implies that every type is a subtype of itself
+also. Furthermore, every type is a subtype of the type
+.codn t ,
+which has no
+supertype other than itself. Type
+.code nil
+is is a subtype of every type, including
+itself. The subtyping relationship is transitive also. If
+.code A
+is a subtype
+of
+.codn B ,
+and
+.code B
+is a subtype of
+.codn C ,
+then
+.code A
+is a subtype of
+.codn C .
+
+.code defex
+may be invoked with no arguments, in which case it does nothing:
+
+.cblk
@(defex)
+.cble
It may be invoked with one argument, which must be a symbol. This introduces a
new exception type. Strictly speaking, such an introduction is not necessary;
any symbol may be used as an exception type without being introduced by
-@(defex):
+.codn @(defex) :
+.cblk
@(defex a)
+.cble
Therefore, this also does nothing, other than document the intent to use
a as an exception.
@@ -5042,164 +8432,258 @@ types, engaged in a subtype-supertype relationship from left to right.
That is to say, the first (leftmost) symbol is a subtype of the next one,
which is a subtype of the next one and so on. The last symbol, if it
had not been already defined as a subtype of some type, becomes a
-direct subtype of the master supertype t. Example:
+direct subtype of the master supertype
+.codn t .
+Example:
+.cblk
@(defex d e)
@(defex a b c d)
-
-The fist directive defines d as a subtype of e, and e as a subtype of t.
-The second defines a as a subtype of b, b as a subtype of c, and
-c as a subtype of d, which is already defined as a subtype of e.
-Thus a is now a subtype of e. It should be obvious that the above
-could be condensed to:
-
+.cble
+
+The first directive defines
+.code d
+as a subtype of
+.codn e ,
+and
+.code e
+as a subtype of
+.codn t .
+The second defines
+.code a
+as a subtype of
+.codn b ,
+.code b
+as a subtype of
+.codn c ,
+and
+.code c
+as a subtype of
+.codn d ,
+which is already defined as a subtype of
+.codn e .
+Thus
+.code a
+is now a subtype of
+.codn e .
+The the above can be condensed to:
+
+.cblk
@(defex a b c d e)
+.cble
Example:
-
- Query: @(defex gorilla ape primate)
- @(defex monkey primate)
- @(defex human primate)
- @(collect)
- @(try)
- @(skip)
- @(cases)
- gorilla @name
- @(throw gorilla name)
- @(or)
- monkey @name
- @(throw monkey name)
- @(or)
- human @name
- @(throw human name)
- @(end)@#cases
- @(catch primate (name))
- @kind @name
- @(output)
- we have a primate @name of kind @kind
- @(end)@#output
- @(end)@#try
- @(end)@#collect
-
-
- Input: gorilla joe
- human bob
- monkey alice
-
- Output: we have a primate joe of kind gorilla
- we have a primate bob of kind human
- we have a primate alice of kind monkey
+.IP code:
+.cblk
+\ @(defex gorilla ape primate)
+ @(defex monkey primate)
+ @(defex human primate)
+ @(collect)
+ @(try)
+ @(skip)
+ @(cases)
+ gorilla @name
+ @(throw gorilla name)
+ @(or)
+ monkey @name
+ @(throw monkey name)
+ @(or)
+ human @name
+ @(throw human name)
+ @(end)@#cases
+ @(catch primate (name))
+ @kind @name
+ @(output)
+ we have a primate @name of kind @kind
+ @(end)@#output
+ @(end)@#try
+ @(end)@#collect
+.cble
+.IP data:
+.cblk
+\ gorilla joe
+ human bob
+ monkey alice
+.cble
+.IP output:
+.cblk
+\ we have a primate joe of kind gorilla
+ we have a primate bob of kind human
+ we have a primate alice of kind monkey
+.cble
+.PP
Exception types have a pervasive scope. Once a type relationship is introduced,
-it is visible everywhere. Moreover, the defex directive is destructive,
+it is visible everywhere. Moreover, the
+.code defex
+directive is destructive,
meaning that the supertype of a type can be redefined. This is necessary so
-that something like the following works right.
+that something like the following works right:
+.cblk
@(defex gorilla ape)
@(defex ape primate)
-
-These directives are evaluated in sequence. So after the first one, the ape
-type has the type t as its immediate supertype. But in the second directive,
-ape appears again, and is assigned the primate supertype, while retaining
-gorilla as a subtype. This situation could instead be diagnosed as an
+.cble
+
+These directives are evaluated in sequence. So after the first one, the
+.code ape
+type has the type
+.code t
+as its immediate supertype. But in the second directive,
+.code ape
+appears again, and is assigned the
+.code primate
+supertype, while retaining
+.code gorilla
+as a subtype. This situation could be diagnosed as an
error, forcing the programmer to reorder the statements, but instead
TXR obliges. However, there are limitations. It is an error to define a
subtype-supertype relationship between two types if they are already connected
by such a relationship, directly or transitively. So the following
definitions are in error:
+.cblk
@(defex a b)
@(defex b c)
@(defex a c)@# error: a is already a subtype of c, through b
@(defex x y)
@(defex y x)@# error: circularity; y is already a supertype of x.
+.cble
-.SS The Assert directive
+.dir assert
-The assert directive requires the remaining query or sub-query which follows it
+The
+.code assert
+directive requires the remaining query or sub-query which follows it
to match. If the remainder fails to match, the assert directive throws an
exception. If the directive is simply
+.cblk
@(assert)
+.cble
Then it throws an assertion of type assert, which is a subtype of error.
The assert directive also takes arguments similar to the throw
directive. The following assert directive, if it triggers, will throw
-an exception of type foo, with arguments 1 and "2".
-
+an exception of type
+.codn foo ,
+with arguments
+.code 1
+and
+.strn 2 :
+
+.cblk
@(assert foo 1 "2")
-
-The throw directive generates an exception. A type must be specified,
-followed by optional arguments.
+.cble
Example:
+.cblk
@(collect)
Important Header
----------------
@(assert)
Foo: @a, @b
@(end)
-
-Without the assertion in places, if the "Foo: @a, @b" part does not
-match, then the entire interior of the @(collect) clause fails,
+.cble
+
+Without the assertion in places, if the
+.code Foo: @a, @b
+part does not
+match, then the entire interior of the
+.code @(collect)
+clause fails,
and the collect continues searching for another match.
-With the assertion in place, if the "Important Header" and its
+With the assertion in place, if the text
+.str "Important Header"
+and its
underline match, then the remainder of the collect body must
match, otherwise an exception is thrown. Now the program will not
silently skip over any Important Header sections due to a problem
in its matching logic. This is particularly useful when the matching is varied
with numerous cases, and they must all be handled.
-There is a horizontal directive also. For instance:
+There is a horizontal
+.code assert
+directive also. For instance:
+.cblk
abc@(assert)d@x
+.cble
-asserts that if the prefix "abc" is matched, then it must be
-followed by a successful match for "d@x", or else an exception
-is thrown.
-
+asserts that if the prefix
+.str abc
+is matched, then it must be
+followed by a successful match for
+.strn "d@x" ,
+or else an exception is thrown.
-.SH TXR LISP
+.SH* TXR LISP
The TXR language contains an embedded Lisp dialect called TXR Lisp.
This language is exposed in TXR in several ways.
Firstly, in any situation that calls for an expression, a Lisp
-expression can be used, if it is preceded by the @ symbol. The Lisp expression
+expression can be used, if it is preceded by the
+.code @
+character. The Lisp expression
is evaluated and its value becomes the value of that expression.
-Thus, TXR directives are embedded in literal text using @, and Lisp expressions
-are embedded in directives using @ also.
-
-Secondly, the @(do) directive can be used for evaluating one or more Lisp
+Thus, TXR directives are embedded in literal text using
+.codn @ ,
+and Lisp expressions
+are embedded in directives using
+.code @
+also.
+
+Secondly, the
+.code @(do)
+directive can be used for evaluating one or more Lisp
forms, such that their value is thrown away. This is useful for evaluating some
Lisp code for the sake of its side effect, such as defining a variable,
updating a hash table, et cetera.
-Thirdly, the @(require) directive can be used to evaluate Lisp expressions
+Thirdly, the
+.code @(require)
+directive can be used to evaluate Lisp expressions
as part of the matching logic of the TXR pattern language. The return value
-of the rightmost expression is examined. If it is nil, then the @(require)
+of the rightmost expression is examined. If it is nil, then the
+.code @(require)
directive triggers a match failure. Otherwise, matching proceeds.
-Lastly, TXR Lisp expressions can be evaluated via the txr command line,
-using the -e and -p options.
+Lastly, TXR Lisp expressions can be evaluated via the
+command line, using the
+.code -e
+and
+.code -p
+options.
+.B
Examples:
-Bind variable a to the integer 4:
+Bind variable
+.code a
+to the integer 4:
+.cblk
@(bind a @(+ 2 2))
+.cble
-Bind variable b to the standard input stream:
+Bind variable
+.code b
+to the standard input stream:
+.cblk
@(bind a @*stdin*)
+.cble
-Define several Lisp functions using @(do):
+Define several Lisp functions inside
+.codn @(do) :
- @(do
+.cblk
+ @(do
(defun add (x y) (+ x y))
(defun occurs (item list)
@@ -5207,258 +8691,439 @@ Define several Lisp functions using @(do):
((atom list) (eql item list))
(t (or (eq (first list) item)
(occurs item (rest list)))))))
+.cble
-Trigger a failure unless previously bound variable "answer" is greater
-than 42:
+Trigger a failure unless previously bound variable
+.code answer
+is greater than 42:
+.cblk
@(require (> (str-int answer) 42)
+.cble
-.SS Overview
+.SS* Overview
TXR Lisp is a small and simple dialect, like Scheme, but much more similar to
Common Lisp than Scheme. It has separate value and function binding namespaces,
like Common Lisp (and thus is a Lisp-2 type dialect), and represents boolean
-true and false with the symbols t and nil (but note the case sensitivity of
-identifiers denoting symbols!) Furthermore, the symbol nil is also the empty
-list, which terminates nonempty lists.
+.B true
+and
+.B false
+with the symbols
+.code t
+and
+.code nil
+(note the case sensitivity of
+identifiers denoting symbols!) Furthermore, the symbol
+.code nil
+is also the empty list, which terminates nonempty lists.
Function and variable bindings are dynamically scoped in TXR Lisp. However,
closures do capture variables.
-.SS Additional Syntax
+.SS* Additional Syntax
Much of the TXR Lisp syntax has been introduced in the previous sections of the
manual, since directive forms are based on it. There is some additional syntax
that is useful in TXR Lisp programming.
-.SS Consing Dot
+.SS* Consing Dot
Unlike other major Lisp dialects, TXR Lisp allows a consing dot with no forms
preceding it. This construct simply denotes the form which follows the dot.
That is to say, the parser implements the following transformation:
+.cblk
(. expr) -> expr
+.cble
This is convenient in writing function argument lists that only take
variable arguments. Instead of the syntax:
+.cblk
(defun fun args ...)
+.cble
the following syntax can be used:
+.cblk
(defun fun (. args) ...)
+.cble
-When a lambda form is printed, it is printed in the following style.
+When a
+.code lambda
+form is printed, it is printed in the following style.
+.cblk
(lambda nil ...) -> (lambda () ...)
(lambda sym ...) -> (lambda (. sym) ...)
(lambda (sym) ...) -> (lambda (sym) ...)
+.cble
-In no other circumstances is nil printed as (), or a symbol as (. sym).
-
-symbol is followed by a symbol.
+In no other circumstances is
+.code nil
+printed as
+.codn () ,
+or an atom
+.code sym
+as
+.codn "(. sym)" .
-.SS Quote and Quasiquote
+.SS* Quote and Quasiquote
-.IP '<expr>
+.meIP >> ' expr
The quote character in front of an expression is used for suppressing evaluation,
which is useful for forms that evaluate to something other than themselves.
-For instance if '(+ 2 2) is evaluated, the value is the three-element list
-(+ 2 2), whereas if (+ 2 2) is evaluated, the value is 4. Similarly, the
-value of 'a is the symbol a itself, whereas the value of a is the value
-of the variable a.
-
-.IP ^<qq-template>
+For instance if
+.code '(+ 2 2)
+is evaluated, the value is the three-element list
+.codn "(+ 2 2)" ,
+whereas if
+.code (+ 2 2)
+is evaluated, the value is
+.codn 4 .
+Similarly, the value of
+.code 'a
+is the symbol
+.code a
+itself, whereas the value of
+.code a
+is the contents of the variable
+.codn a .
+
+.meIP >> ^ qq-template
The caret in front of an expression is a quasiquote. A quasiquote is like
a quote, but with the possibility of substitution of material.
Under a quasiquote, form is considered to be a quasiquote template. The template
is considered to be a literal structure, except that it may contain
-the notations ,<expr> and ,*<expr> which denote non-constant parts.
+the notations
+.cblk
+.meti >> , expr
+.cble
+and
+.cblk
+.meti >> ,* expr
+.cble
+which denote non-constant parts.
A quasiquote gets translated into code which, when evaluated, constructs
-the structure implied by <qq-template>, taking into account the unquotes
-and splices.
+the structure implied by
+.metn qq-template ,
+taking into account the unquotes and splices.
A quasiquote also processes nested quasiquotes specially.
-If <qq-template> does not contain any unquotes or splices (which match its
-level of nesting), or is simply an atom, then ^<qq-template> is equivalent to
-'<qq-template>: in other words, it is like an ordinary quote. For instance ^(a
-b ^(c ,d)) is equivalent to '(a b ^(c ,d)). Although there is an unquote ,d it
-belongs to the inner quasiquote ^(c ,d), and the outer quasiquote does not have
+If
+.meta qq-template
+does not contain any unquotes or splices (which match its
+level of nesting), or is simply an atom, then
+.cblk
+.meti >> ^ qq-template
+.cble
+is equivalent to
+.cblk
+.meti >> ' qq-template .
+.cble
+in other words, it is like an ordinary quote. For instance
+.code ^(a b ^(c ,d))
+is equivalent to
+.codn '(a b ^(c ,d)) .
+Although there is an unquote ,d it
+belongs to the inner quasiquote
+.codn ^(c ,d) ,
+and the outer quasiquote does not have
any unquotes of its own, making it equivalent to a quote.
-Dialect note: in Common Lisp and Scheme, ^form is written `form, and
-quasiquotes are also informally known as backquotes. In TXR, the backquote is
-used for quasi string literals already. Moreover, the caret is more visually
-distinct from the backquote, making it somewhat easier to tell apart generated
-code from its surroundings.
-
-.IP ,<expr>
-
-The comma character is used within a <qq-template> to denote an unquote. Whereas
+Dialect note: in Common Lisp and Scheme,
+.code ^form
+is written
+.codn `form ,
+and
+quasiquotes are also informally known as backquotes. In TXR, the backquote
+character
+.code `
+used for quasi string literals.
+
+.meIP >> , expr
+
+The comma character is used within a
+.meta qq-template
+to denote an unquote. Whereas
the quote suppresses evaluation, the comma introduces an exception: an element
-of a form which is evaluated. For example, list ^(a b c ,(+ 2 2)
-(+ 2 2)) is the list (a b c 4 (+ 2 2)). Everything
-in the quasiquote stands for itself, except for the ,(+ 2 2) which is evaluated.
-
-Note: if a variable is called *x*, then the syntax ,*x* means ,* x*: splice
-the value of x*. In this situation, whitespace between the comma and the
-variable name should be used: , *x*.
-
-.IP ,*<expr>
-
-The comma-star operator is used within quasiquote list to denote a splicing unquote.
-The form which follows ,* must evaluate to a list. That list is spliced into
-the structure which the quasiquote denotes. For example: '(a b c ,*(list
-(+ 3 3) (+ 4 4) d)) evaluates to (a b c 6 8 d). The expression (list (+ 3 3)
-(+ 4 4)) is evaluated to produce the list (6 8), and this list is spliced into
-the quoted template.
-
-Dialect note: in other Lisp dialects, the equivalent syntax is usually ,@
-(comma at). The @ character already has an assigned meaning, so * is used.
-
-.SS Quasiquoting non-List Objects
-
+of a form which is evaluated. For example, list
+.code ^(a b c ,(+ 2 2) (+ 2 2))
+is the list
+.codn (a b c 4 (+ 2 2)) .
+Everything
+in the quasiquote stands for itself, except for the
+.code ,(+ 2 2)
+which is evaluated.
+
+Note: if a variable is called
+.codn *x* ,
+then the syntax
+.code ,*x*
+means
+.codn ,* x* :
+splice
+the value of
+.codn x* .
+In this situation, whitespace between the comma and the
+variable name should be used:
+.codn , *x* .
+
+.meIP >> ,* expr
+
+The comma-star operator is used within quasiquote list to denote a splicing
+unquote. The form which follows
+.code ,*
+must evaluate to a list. That list is spliced into
+the structure which the quasiquote denotes. For example:
+.code '(a b c ,*(list (+ 3 3) (+ 4 4) d))
+evaluates to
+.codn "(a b c 6 8 d)" .
+The expression
+.code (list (+ 3 3) (+ 4 4))
+is evaluated to produce the list
+.codn "(6 8)" ,
+and this list is spliced into the quoted template.
+
+Dialect note: in other Lisp dialects, the equivalent syntax is usually
+.code ,@
+(comma at). The
+.code @
+character already has an assigned meaning, so
+.code *
+is used.
+
+.SS* Quasiquoting non-List Objects
Quasiquoting is supported over hash table and vector literals (see Vectors
and Hashes below). A hash table or vector literal can be quoted, like any
object, for instance:
+.cblk
'#(1 2 3)
-
-The #(1 2 3) literal is turned into a vector atom right in the TXR parser,
-and this atom is being quoted: this is (quote <atom>) syntactically,
-which evaluates to <atom>.
-
-When a vector is quasi-quoted, this is a case of ^<atom>, which
-evaluates to <atom>.
-
+.cble
+
+The
+.code #(1 2 3)
+literal is turned into a vector atom right in the TXR parser,
+and this atom is being quoted: this is
+.cblk
+.meti (quote << atom )
+.cble
+syntactically, which evaluates to
+.metn atom .
+
+When a vector is quasi-quoted, this is a case of
+.cblk
+.meti >> ^ atom
+.cble
+which evaluates to
+.metn atom .
+
+A vector can be quasiquoted, for example:
+
+.cblk
^#(1 2 3)
+.cble
-If unquotes occur in the quasi-quoted vector, it is a quasivector.
+Of ourse, unquotes can occur within it.
+.cblk
(let ((a 42))
^#(1 ,a 3)) ; value is #(1 42 3)
+.cble
-In this situation, the ^#(...) notation produces code which constructs
-a vector.
+In this situation, the
+.code ^#(...)
+notation produces code which constructs a vector.
The vector in the following example is also a quasivector. It contains
-unquotes, and is though the quote is not directly applied to it,
-it is surrounded in a quote.
+unquotes, and though the quasiquote is not directly applied to it,
+it is embedded in a quasiquote:
+.cblk
(let ((a 42))
^(a b c #(d ,a))) ; value is (a b c #(d 42))
+.cble
Hash table literals have two parts: the list of hash construction
arguments and the key-value pairs. For instance:
+.cblk
#H((:equal-based) (a 1) (b 2))
-
-where (:equal-based) is the list of arguments and the pairs are (a 1) and (b
-2). Hash literals may be quasiquoted. In quasiquoting, the arguments and pairs
-are treated as separate syntax; it is not one big list. So the following is
-not a possible way to express the above hash:
-
+.cble
+
+where
+.code (:equal-based)
+is the list of construction arguments and the pairs
+.code (a 1)
+and
+.code (b 2)
+are the key/value entries. Hash literals may be quasiquoted. In
+quasiquoting, the arguments and pairs are treated as separate syntax; it is not
+one big list. So the following is not a possible way to express the above
+hash:
+
+.cblk
;; not supported: splicing across the entire syntax
(let ((hash-syntax '((:equal-based) (a 1) (b 2))))
^#H(,*hash-syntax))
+.cble
This is correct:
+.cblk
;; fine: splicing hash arguments and contents separately
(let ((hash-args '(:equal-based))
(hash-contents '((a 1) (b 2))))
^#H(,hash-args ,*hash-contents))
+.cble
-.SS Quasiquoting combined with Quasiliterals
-
+.SS* Quasiquoting combined with Quasiliterals
When a quasiliteral is embedded in a quasiquote, it is possible to use
splicing to insert material into the quasiliteral.
-.TP
Example:
+.cblk
(eval (let ((a 3)) ^`abc @,a @{,a} @{(list 1 2 ,a)}`))
-> "abc 3 3 1 2 3"
+.cble
-.SS Vectors
+.SS* Vectors
-.IP "#(...)"
+.coIP "#(...)"
-A hash token followed by a list denotes a vector. For example #(1 2 a)
-is a three-element vector containing the numbers 1 and 2, and the symbol a.
+A hash token followed by a list denotes a vector. For example
+.code #(1 2 a)
+is a three-element vector containing the numbers
+.code 1
+and
+.codn 2 ,
+and the symbol
+.codn a .
-.SS Hashes
+.SS* Hashes
-.IP "#H((<hash-argument>*) (<key> <value>)*)"
+.meIP <> #H(( hash-argument *) >> ( key << value )*)
-The notation #H followed by a nested list syntax denotes a hash table literal.
+The notation
+.code #H
+followed by a nested list syntax denotes a hash table literal.
The first item in the syntax is a list of keywords. These are the same
keywords as are used when calling the function hash to construct
-a hash table. Allowed keywords are: :equal-based, :weak-keys, :weak-values.
-An empty list can be specified as nil or (), which defaults to a
-hash table based on the eq function, with no weak semantics.
-
-.SS The .. notation
-
+a hash table. Allowed keywords are:
+.codn :equal-based ,
+.code :weak-keys
+and
+.codn :weak-values .
+An empty list can be specified as
+.code nil
+or
+.codn () ,
+which defaults to a
+hash table based on the
+.code eql
+function, with no weak semantics.
+
+.coSS The @ .. notation
In TXR Lisp, there is a special "dotdot" notation consisting of a pair of dots.
This can be written between successive atoms or compound expressions, and is a
shorthand for cons.
-That is to say, A .. B translates to (cons A B), and so for instance
-(a b .. (c d) e .. f . g) means (a (cons b (c d)) (cons e f) . g).
+That is to say,
+.code A .. B
+translates to
+.codn "(cons A B)" ,
+and so for instance
+.code (a b .. (c d) e .. f . g)
+means
+.codn "(a (cons b (c d)) (cons e f) . g)" .
This is a syntactic sugar useful in certain situations in which a cons is used
-to represent a pair of numbers or other objects. For instance, if L
-is a list, then [L 1 .. 3] computes a sublist of L consisting of
+to represent a pair of numbers or other objects. For instance, if
+.code L
+is a list, then
+.code [L 1 .. 3]
+computes a sublist of
+.code L
+consisting of
elements 1 through 2 (counting from zero).
-.TP
-Restrictions:
+Restrictions:
-The notation must be enclosed in a list. For instance a..b is not an
-expression, but (a..b) is. This is important if Lisp data is being parsed from
-a string or stream using the read function. If the data "a..b" is
-parsed, the symbol "a" will be extracted, leaving "..a", which, if parsed,
+The notation must be enclosed in a list. For instance
+.code a..b
+is not, by itself, an
+expression, but
+.code (a..b)
+is. This is important if Lisp data is being parsed from
+a string or stream using the read function. If the data
+.str "a..b"
+is parsed, the symbol
+.code a
+will be extracted, leaving
+.strn ..a ,
+which, if parsed,
produces a syntax error since it consists of a "dotdot" token followed by
-a symbol, which is not valid syntax, akin to something like ")a" or ".a".
+a symbol, which is not valid syntax.
-The notation cannot occur in the dot position; that is, the syntax (a . b .. c)
+The notation cannot occur in the dot position; that is, the syntax
+.code (a . b .. c)
is invalid. The dotdot operator can only be used between the non-dot-position
elements of a list.
-.SS The DWIM Brackets
-
-TXR Lisp has a square bracket notation. The syntax [...] is a shorthand
-way of writing (dwim ...). The [] syntax is useful for situations
+.SS* The DWIM Brackets
+TXR Lisp has a square bracket notation. The syntax
+.code [...]
+is a shorthand
+way of writing
+.codn "(dwim ...)" .
+The
+.code []
+syntax is useful for situations
where the expressive style of a Lisp-1 dialect is useful.
-For instance if foo is a variable which holds a function object, then [foo 3]
-can be used to call it, instead of (call foo 3). If foo is a vector, then
-[foo 3] retrieves the fourth element, like (vecref foo 3). Indexing over lists,
+For instance if
+.code foo
+is a variable which holds a function object, then
+.code [foo 3]
+can be used to call it, instead of
+.codn "(call foo 3)" .
+If foo is a vector, then
+.code [foo 3]
+retrieves the fourth element, like
+.codn "(vecref foo 3)" .
+Indexing over lists,
strings and hash tables is possible, and the notation is assignable.
-Furthermore, any arguments enclosed in [] which are symbols are treated
+Furthermore, any arguments enclosed in
+.code []
+which are symbols are treated
according to a modified namespace lookup rule.
-More details are given in the documentation for the dwim operator.
-
-.SS Compound Forms
+More details are given in the documentation for the
+.code dwim
+operator.
+.SS* Compound Forms
In TXR Lisp, there are two types of compound forms: the Lisp-2 style
compound forms, denoted by ordinary lists that are expressed with parentheses.
There are Lisp-1 style compound forms denoted by the DWIM Brackets, discussed
in the previous section.
The first position of an ordinary Lisp-2 style compound form, is expected to
-have a function or operator name. Then arguments follow. Finally, there may
+have a function or operator name. Then arguments follow. There may
also be an expression in the dotted position, if the form is a function call.
+The following are Lisp functions and variables built-in to TXR.
+
If the form is a function call then the arguments are evaluated. If any of the
arguments are symbols, they are treated according to Lisp-2 namespacing rules.
@@ -5466,9 +9131,12 @@ Additionally, if there is an expression in the dotted position, it is also
evaluated. It should evaluate to a sequence: a list, vector or string. The
elements of the sequence generate additional arguments for the function
call. Note, however, that a compound form cannot be used in the dot position,
-for obvious reasons, namely that (a b c . (foo z)) does not mean that there is
-a compound form in the dot position, but a different spelling for
-(a b c foo z), where foo behaves as a variable.
+for obvious reasons, namely that
+.code (a b c . (foo z))
+does not mean that there is
+a compound form in the dot position, but denotes an alternate spelling for
+.codn "(a b c foo z)" ,
+where foo behaves as a variable.
The DWIM brackets are similar, except that the first position is an arbitrary
expression which is evaluated according to the same rules as the remaining
@@ -5478,9 +9146,9 @@ list or hash. Operators are not supported. The dotted syntax for application
of additional arguments from a list or vector is supported in the DWIM
brackets just like in the parentheses.
-.TP
Examples:
+.cblk
;; a contains 3
;; b contains 4
;; c contains #(5 6 7)
@@ -5493,8 +9161,8 @@ Examples:
[foo a b . c] ;; calls (foo 3 4 5 6 7)
[c 1] ;; indexes into vector #(5 6 7) to yield 6
+.cble
-.TP
Dialect Note:
In some other Lisp dialects, the improper list syntax is not supported;
@@ -5502,24 +9170,48 @@ a function called apply (or similar) must be used for application even if
the expression which gives the trailing arguments is a symbol. Moreover,
applying sequences other than lists is not supported.
-.SS Regular Expressions
-
-In TXR Lisp, the / character can occur in symbol names, and the / token
-is a symbol. Therefore the /regex/ syntax is absent, replaced with the
-#/regex/ syntax.
-
-.SS Generalization of List Accessors car and cdr
-
+.SS* Regular Expressions
+In TXR Lisp, the
+.code /
+character can occur in symbol names, and the
+.code /
+token
+is a symbol. Therefore the
+.code /regex/
+syntax is not used for denoting regular expressions; rather, the
+.code #/regex/
+syntax is used.
+
+.coSS Generalization of List Accessors
In ancient Lisp in the 1960's, it was not possible to apply the operations
-car and cdr to the nil symbol (empty list), because it is not a cons cell. In
+.code car
+and
+.code cdr
+to the
+.code nil
+symbol (empty list), because it is not a
+.code cons
+cell. In
the InterLisp dialect, this restriction was lifted: these operations were
-extended to accept nil (and return nil). The convention was adopted in
+extended to accept
+.code nil
+(and return
+.codn nil ).
+The convention was adopted in
other Lisp dialects such as MacLisp and eventually in Common Lisp. Thus there
-exists an object which is not a cons, yet which takes car and cdr.
+exists an object which is not a cons, yet which takes
+.code car
+and
+.codn cdr .
In TXR Lisp, this relaxation is extended further. For the sake of convenience,
-the operations car and cdr, are extended to work with strings and vectors:
+the operations
+.code car
+and
+.codn cdr ,
+are made to work with strings and vectors:
+.cblk
(cdr "") -> nil
(car "") -> nil
@@ -5528,36 +9220,79 @@ the operations car and cdr, are extended to work with strings and vectors:
(cdr #(1 2 3)) -> #(2 3)
(car #(1 2 3)) -> 1
+.cble
-The ldiff function is also extended in a special way. When the right parameter
+The
+.code ldiff
+function is also extended in a special way. When the right parameter
is a string or vector, then it uses the equal equality test rather than eq
for detecting the tail of the list.
+.cblk
(ldiff "abcd" "cd") -> (#\ea #\eb)
-
-The ldiff operation starts with "abcd" and repeatedly applies cdr to produce
-"bcd" and "cd", until the suffix is equal to the second argument: (equal "cd"
-"cd") yields true.
-
-Operations based on car, cdr and ldiff, such as keep-if and remq extend to
+.cble
+
+The
+.code ldiff
+operation starts with
+.str "abcd"
+and repeatedly applies
+.code cdr
+to produce
+.str "bcd"
+and
+.strn "cd" ,
+until the suffix is equal to the second argument:
+.cblk
+(equal "cd" "cd")
+.cble
+yields true.
+
+Operations based on
+.codn car ,
+.code cdr
+and
+.codn ldiff ,
+such as
+.code keep-if
+and
+.code remq
+extend to
strings and vectors.
-Derived list processing operations such as remq or mapcar obey the following
+Most derived list processing operations such as
+.code remq
+or
+.code mapcar
+obey the following
rule: the returned object follows the type of the leftmost input list object.
-For instance, if one or more sequences are processed by mapcar, and the
+For instance, if one or more sequences are processed by
+.codn mapcar ,
+and the
leftmost one is a character string, the function is expected to return
characters, which are converted to a character string. However, in the
event that the objects produced cannot be assembled into that type of
sequence, a list is returned instead.
-For example [mapcar list "ab" "12"] returns ((#\ea #\eb) (#\e1 #\e2)),
+For example
+.cblk
+[mapcar list "ab" "12"]
+.cble
+returns
+.codn "((#\ea #\eb) (#\e1 #\e2))" ,
because a string cannot hold lists of characters. However
-[mappend list "ab" "12"] returns "a1b2".
-
-The lazy versions of these functions such as mapcar* do not have this behavior;
+.cblk
+[mappend list "ab" "12"]
+.cble
+returns
+.strn "a1b2" .
+
+The lazy versions of these functions such as
+.code mapcar*
+do not have this behavior;
they produce lazy lists.
-.SS Callable Objects
+.SS* Callable Objects
In TXR Lisp, sequences (strings, vectors and lists) and hashes can be used
as functions everywhere, not just with the DWIM brackets. Sequences work
@@ -5569,38 +9304,63 @@ to the arguments of the gethash function.
Moreover, when a sequence is used as a function of one argument, and the
argument is a cons cell rather than an integer, then the call becomes a
two-argument call in which the car and cdr of the cell are passed as separate
-arguments. This allows for syntax like (call "abc" 0..1).
+arguments. This allows for syntax like
+.cblk
+(call "abc" 0..1).
+.cble
-.TP
-Example 1:
+.B Example 1:
+.cblk
(mapcar "abc" '(2 0 1)) -> (#\ec #\ea #\eb)
-
-Here, mapcar treats the string "abc" as a function of one argument (since there
-is one list argument). This function maps the indices 0, 1 and 2 to the
-corresponding characters of string "abc". Through this function, the list of
-integer indices (2 0 1) is taken to the list of characters (#\ec #\ea #\eb).
-
-.TP
-Example 2:
-
+.cble
+
+Here,
+.code mapcar
+treats the string
+.str abc
+as a function of one argument (since there
+is one list argument). This function maps the indices
+.codn 0 ,
+.code 1
+and
+.code 2
+to the
+corresponding characters of string
+.strn abc .
+Through this function, the list of
+integer indices
+.code (2 0 1)
+is taken to the list of characters
+.codn (#\ec #\ea #\eb) .
+
+.B Example 2:
+
+.cblk
(call '(1 2 3 4) 1..3) -> (2 3)
+.cble
-Here, the shorthand 1 .. 3 denotes (cons 1 3). A cons cell as an argument
+Here, the shorthand
+.code 1 .. 3
+denotes
+.codn (cons 1 3) .
+A cons cell as an argument
to a sequence performs range extraction: taking a slice starting at
index 1, up to and not including index 3, as if by the call
-(sub '(1 2 3 4) 1 3).
+.codn (sub '(1 2 3 4) 1 3) .
-.TP
-Example 3:
+.B Example 3:
+.cblk
(call '(1 2 3 4) '(0 2)) -> (1 2)
+.cble
A list of indices applied to a sequence is equivalent to using the
-select function, as if (select '(1 2 3 4) '(0 2)) were called.
-
-.SS Special Variables
+select function, as if
+.code (select '(1 2 3 4) '(0 2))
+were called.
+.SS* Special Variables
Similarly to Common Lisp, TXR Lisp is lexically scoped by default, but
also has dynamically scoped (a.k.a "special") variables.
@@ -5611,7 +9371,9 @@ Furthermore, at the time the defvar form is evaluated, the symbol which
names the variable is tagged as special.
When a symbol is tagged as special, it behaves differently when it is used
-in a lexical binding construct like let, and all other such constructs
+in a lexical binding construct like
+.codn let ,
+and all other such constructs
such as function parameter lists. Such a binding is not the usual lexical
binding, but a "rebinding" of the global variable. Over the dynamic scope
of the form, the global variable takes on the value given to it by the
@@ -5628,9 +9390,9 @@ Certain variables in TXR's library break this convention; however, they at
least have distinct prefixes, examples being example s-ifmt, log-emerg and
sig-hup.
-.TP
Example:
+.cblk
(defvar *x* 42) ;; *x* has a value of 42
(defun print-x ()
@@ -5640,25 +9402,26 @@ Example:
(print-x)) ;; *x* is now "abc" and so that is printed
(print-x) ;; *x* is 42 again and so "42" is printed
+.cble
-
-
-.SH OPERATOR AND FUNCTION LIBRARY
-
+.SH* TXR LISP OPERATOR AND FUNCTION LIBRARY
A compound expression with a symbol as its first element, if
intended to be evaluated, denotes either an operator invocation or a function
call. This depends on whether the symbol names an operator or a function.
When the form is an operator invocation, the interpretation of the meaning of
-that form is under the complete control of that operator.
+that form is under the complete control of that operator.
-Functions calls do not control the evaluation of the function call forms which
-invoke them; function call forms are evaluated according to very regular rules
-that apply to all function calls.
+If the compound form is a function call, the remaining forms, if any, denote
+argument expressions to the function. They are evaluated in left to right
+order to produce the argument values, which are passed to the function. An
+exception is thrown if there are not enough arguments, or too many. Programs
+can define named functions with the defun operator
Some operators are macros. There exist predefined macros in the library, and
macro operators can also be user-defined using the macro-defining operator
-defmacro. Operators that are not macros are called special operators.
+.codn defmacro .
+Operators that are not macros are called special operators.
Macro operators work as functions which are given the source code of the form.
They analyze the form, and translate it to another form which is substituted in
@@ -5676,435 +9439,639 @@ and functions in TXR Lisp.
In these sections Syntax is indicated using these conventions:
-.TP
-<word>
-
-A symbol in angle brackets denotes some syntactic unit: it
+.ie n \{\
+. coIP <word>
+A symbol in angle brackets
+.\}
+.el \{\
+. coIP \f[5]word\f[]
+A symbol in
+.meta fixed-width-italic
+font
+.\}
+denotes some syntactic unit: it
may be a symbol or compound form. The syntactic unit is explained
in the Description section.
-.TP
-{syntax}* <word>*
-
+.ie n \{\
+.coIP {syntax}* <word>*
+.\}
+.el \{\
+.coIP {syntax}* \f[5]word\f[]*
+.\}
This indicates a repetition of zero or more of the given
syntax enclosed in the braces or syntactic unit.
-.TP
-{syntax}+ <word>+
-
+.ie n \{\
+.coIP {syntax}+ <word>+
+.\}
+.el \{\
+.coIP {syntax}+ \f[5]word\f[]+
+.\}
This indicates a repetition of one or more of the given
syntax enclosed in the braces or syntactic unit.
-.TP
-[syntax] [<word>]
-
+.ie n \{\
+.coIP [syntax] [<word>]
+.\}
+.el \{\
+.coIP [syntax] [\f[5]word\f[]]
+.\}
Square brackets indicate optional syntax.
-.TP
-alternative1 | alternative2 | ... | alternativeN
-
+.coIP alternative1 | alternative2 | ... | alternativeN
Multiple syntactic variations allowed in one place are
indicated as bar-separated items.
-.SH CONTROL FLOW AND SEQUENCING
-
-.SS Operators progn and prog1
-
-.TP
-Syntax:
-
- (progn <form>*)
- (prog1 <form>*)
-
-.TP
-Description
-
-The progn operator evaluates forms in order, and returns the value
-of the last form. The return value of (progn) is nil.
-
-The prog1 operator evaluates forms in order, and returns the value
-of the first form. The return value of (prog1) is nil.
-
-Various other operators such as let also arrange for the evaluation
+.SS* Control Flow and Sequencing
+.coNP Operators @ progn and @ prog1
+.synb
+.mets (progn << form *)
+.mets (prog1 << form *)
+.syne
+.desc
+The
+.code progn
+operator evaluates forms in order, and returns the value
+of the last form. The return value of the form
+.code (progn)
+is
+.codn nil .
+
+The
+.code prog1
+operator evaluates forms in order, and returns the value
+of the first form. The return value of the form
+.code (prog1)
+is
+.codn nil .
+
+Various other operators such as
+.code let
+also arrange for the evaluation
of a body of forms, the value of the last of which is returned.
-These operators are said to feature an "implicit progn".
-
-.SS Operator cond
-
-.TP
-Syntax:
-
- (cond {(<test> {form}*)}*)
-
-.TP
-Description:
-
-The cond operator provides a multi-branching conditional evaluation of
+These operators are said to feature an implicit
+.codn progn .
+
+.coNP Operator @ cond
+.synb
+.mets (cond >> {( test << form *)}*)
+.syne
+.desc
+The
+.code cond
+operator provides a multi-branching conditional evaluation of
forms. Enclosed in the cond form are groups of forms expressed as lists.
Each group must be a list of at least one form.
The forms are processed from left to right as follows: the first form,
-<test>, in each group is evaluated. If it evaluates true, then the remaining
+.metn test ,
+in each group is evaluated. If it evaluates true, then the remaining
forms in that group, if any, are also evaluated. Processing then terminates and
the result of the last form in the group is taken as the result of cond.
-If <test> is the only form in the group, then result of <test> is taken
-as the result of cond.
-
-If the first form of a group yields nil, then processing continues with the
-next group, if any. If all form groups yield nil, then the cond form yields
-nil. This holds in the case that the syntax is empty: (cond) yields nil.
-
-.SS Macros caseq, caseql and casequal
-
-.TP
-Syntax:
-
- (caseq <test-form> <normal-clause>* [<else-clause>])
- (caseql <test-form> <normal-clause>* [<else-clause>])
- (caseqqual <test-form> <normal-clause>* [<else-clause>])
-
-.TP
-Description:
-
-These three macros arrange for the evaluation of of <test-form>, whose value
-is then compared against the key or keys in each <normal-clause> in turn.
-When the value matches a key, then the remaining forms of <normal-clause>
+If
+.meta test
+is the only form in the group, then result of
+.meta test
+is taken
+as the result of
+.codn cond .
+
+If the first form of a group yields
+.codn nil ,
+then processing continues with the
+next group, if any. If all form groups yield
+.codn nil ,
+then the cond form yields
+.codn nil .
+This holds in the case that the syntax is empty:
+.code (cond)
+yields
+.codn nil .
+
+.coNP Macros @, caseq @ caseql and @ casequal
+.synb
+.mets (caseq < test-form << normal-clause * <> [ else-clause ])
+.mets (caseql < test-form << normal-clause * <> [ else-clause ])
+.mets (caseqqual < test-form << normal-clause * <> [ else-clause ])
+.syne
+.desc
+These three macros arrange for the evaluation of of
+.metn test-form ,
+whose value is then compared against the key or keys in each
+.meta normal-clause
+in turn.
+When the value matches a key, then the remaining forms of
+.meta normal-clause
are evaluated, and the value of the last form is returned; subsequent
clauses are not evaluated. When the value doesn't match any of the keys
-of a <normal-clause> then the next <normal-clause> is tested.
-If all these clauses are exhausted, and there is no <else-clause>,
-then the value nil is returned. Otherwise, the forms in the <else-clause>
+of a
+.meta normal-clause
+then the next
+.meta normal-clause
+is tested.
+If all these clauses are exhausted, and there is no
+.metn else-clause ,
+then the value nil is returned. Otherwise, the forms in the
+.meta else-clause
are evaluated, and the value of the last one is returned.
-The syntax of a <normal-clause> takes on these two forms:
-
- (<key> <form>*)
-
-where <key> may be an atom which denotes a single key, or else a list
-of keys. There is a restriction that the symbol t may not be used
-as <key>. The form (t) may be used as a key to match that symbol.
-
-The syntax of an <else-clause> is:
-
- (t <form>*)
+The syntax of a
+.meta normal-clause
+takes on these two forms:
+
+.cblk
+.mets >> ( key << form *)
+.cble
+
+where
+.meta key
+may be an atom which denotes a single key, or else a list
+of keys. There is a restriction that the symbol
+.code t
+may not be used
+as
+.metn key .
+The form
+.code (t)
+may be used as a key to match that symbol.
+
+The syntax of an
+.meta else-clause
+is:
+
+.cblk
+.mets (t << form *)
+.cble
which resembles a form that is often used as the final clause
-in the cond syntax.
+in the
+.code cond
+syntax.
The three forms of the case construct differ from what type of
-test they apply between the value of <test-form> and the keys.
-The caseq macro generates code which uses the eq function's
-equality. The caseql macro uses eql, and casequal uses equal.
-
-.TP
-Example:
-
+test they apply between the value of
+.meta test-form
+and the keys.
+The
+.code caseq
+macro generates code which uses the
+.code eq
+function's
+equality. The
+.code caseql
+macro uses
+.codn eql ,
+and
+.code casequal
+uses
+.codn equal .
+
+.TP* Example
+.cblk
(let ((command-symbol (casequal command-string
(("q" "quit") 'quit)
(("a" "add") 'add)
(("d" "del" "delete") 'delete)
(t 'unknown))))
...)
-
-.SS Macros when and unless
-
-.TP
-Syntax:
-
- (when <expression> <form>*)
- (unless <expression> <form>*)
-
-.TP
-Description:
-
-The when macro operator evaluates <expression>. If <expression> yields
-true, and there are additional forms, then each <form> is evaluated.
+.cble
+
+.coNP Macros @ when and @ unless
+.synb
+.mets (when < expression << form *)
+.mets (unless < expression << form *)
+.syne
+.desc
+The when macro operator evaluates
+.metn expression .
+If
+.meta expression
+yields
+true, and there are additional forms, then each
+.meta form
+is evaluated.
The value of the last form is becomes the result value of the when form.
-If there are no forms, then the result is nil.
+If there are no forms, then the result is
+.codn nil .
-The unless operator is similar to when, except that it reverses the
+The
+.code unless
+operator is similar to when, except that it reverses the
logic of the test. The forms, if any, are evaluated if, and only if
-<expression> is false.
-
-.SS Macros while and until
-
-.TP
-Syntax:
-
- (while <expression> <form>*)
- (until <expression> <form>*)
-
-.TP
-Description:
-
-The while macro operator provides a looping construct. It evaluates
-<expression>. If <expression> yields nil, then the evaluation of the while form
-terminates, producing the value nil. Otherwise, if there are additional forms,
-then each <form> is evaluated. Next, evaluation returns to <expression>,
+.meta expression
+is false.
+
+.coNP Macros @ while and @ until
+.synb
+.mets (while < expression << form *)
+.mets (until < expression << form *)
+.syne
+.desc
+The
+.code while
+macro operator provides a looping construct. It evaluates
+.metn expression .
+If
+.meta expression
+yields
+.codn nil ,
+then the evaluation of the
+.code while
+form
+terminates, producing the value
+.codn nil .
+Otherwise, if there are additional forms,
+then each
+.meta form
+is evaluated. Next, evaluation returns to
+.metn expression ,
repeating all of the previous steps.
-The until macro operator is similar to while, except that the until form
-terminates when <expression> evaluates true, rather than false.
+The
+.code until
+macro operator is similar to while, except that the until form
+terminates when
+.meta expression
+evaluates true, rather than false.
These operators arrange for the evaluation of all their enclosed forms
-in an anonymous block. Any of the <form>-s, or <expression>, may use
-the return operator to terminate the loop, and optionally to specify
+in an anonymous block. Any of the
+.metn form s,
+or
+.metn expression ,
+may use
+the
+.code return
+operator to terminate the loop, and optionally to specify
a result value for the form.
-The only way these forms can yield a value other than nil is if
-the return operator is used to terminate the implicit anonymous block,
+The only way these forms can yield a value other than
+.code nil
+is if the
+.code return
+operator is used to terminate the implicit anonymous block,
and is given an argument, which becomes the result value.
-.SS Operator/function if
-
-.TP
-Syntax:
-
- (if <cond> <t-form> [<e-form>])
- [if <cond> <then> [<else>]]
-
-.TP
-Description:
-
-There exist both an if operator and an if function. A list form with the symbol
-if in the fist position is interpreted as an invocation of the if operator.
+.coNP Operator/function @ if
+.synb
+.mets (if < cond < t-form <> [ e-form ])
+.mets [if < cond < then <> [ else ]]
+.syne
+.desc
+There exist both an
+.code if
+operator and an
+.code if
+function. A list form with the symbol
+.code if
+in the fist position is interpreted as an invocation of the
+.code if
+operator.
The function can be accessed using the DWIM bracket notation and in other
ways.
-The if operator provides a simple two-way-selective evaluation control.
-The <cond> form is evaluated. If it yields true then <t-form> is
-evaluated, and that form's return value becomes the return value of the if.
-If <cond> yields false, then <e-form> is evaluated and its return value
-is taken to be that of if. If <e-form> is omitted, then the behavior is
-as if <e-form> were specified as nil.
-
-The if function provides no evaluation control. All of arguments
-are evaluated from left to right. If the <cond> argument is true, then it
-returns the <then> argument, otherwise it returns the value of the
-<else> argument, if present, otherwise it returns nil.
-
-.SS Operator/function and
-
-.TP
-Syntax:
-
- (and {<form>}*)
- [and {<arg>]*)
-
-.TP
-Description:
-
-There exist both an and operator and an and function. A list form with the
-symbol and in the fist position is interpreted as an invocation of the
+The
+.code if
+operator provides a simple two-way-selective evaluation control.
+The
+.meta cond
+form is evaluated. If it yields true then
+.meta t-form
+is evaluated, and that form's return value becomes the return value of the
+.codn if .
+If
+.meta cond
+yields false, then
+.meta e-form
+is evaluated and its return value is taken to be that of
+.codn if .
+If
+.meta e-form
+is omitted, then the behavior is as if
+.meta e-form
+were specified as
+.codn nil .
+
+The
+.code if
+function provides no evaluation control. All of arguments
+are evaluated from left to right. If the
+.meta cond
+argument is true, then it
+returns the
+.meta then
+argument, otherwise it returns the value of the
+.meta else
+argument if present, otherwise it returns
+.codn nil .
+
+.coNP Operator/function @ and
+.synb
+.mets (and << form *)
+.mets [and << arg *]
+.syne
+.desc
+There exist both an
+.code and
+operator and an
+.code and
+function. A list form with the
+symbol
+.code and
+in the fist position is interpreted as an invocation of the
operator. The function can be accessed using the DWIM bracket notation and in
other ways.
-The and operator provides three functionalities in one. It computes the
+The
+.code and
+operator provides three functionalities in one. It computes the
logical "and" function over several forms. It controls evaluation (a.k.a.
-"short-circuiting"). It also allows the convenient substitution of an
-arbitrary true value in the true case.
-
-The and operator evaluates as follows. First, a return value is
-established and initialized to the value t. The forms, if any, are
+"short-circuiting"). It also provides an idiom for the convenient substitution
+of a value in place of
+.code nil
+when some other values are all true.
+
+The
+.code and
+operator evaluates as follows. First, a return value is
+established and initialized to the value
+.codn t .
+The
+.metn form s,
+if any, are
evaluated from left to right. The return value is overwritten with
the result of each form. Evaluation stops when all forms are exhausted,
-or when any of them yields nil. When evaluation stops, the operator yields
-the return value.
-
-The and function provides no evaluation control; it receives all of its
-arguments fully evaluated. If it is given no arguments, it returns t.
-If it is given one or more arguments, and any of them are nil, it returns
-nil. Otherwise it returns the value of the last argument.
-
-.TP
-Examples:
-
+or when
+.code nil
+is stored in the return value.
+When evaluation stops, the operator yields the return value.
+
+The
+.code and
+function provides no evaluation control; it receives all of its
+arguments fully evaluated. If it is given no arguments, it returns
+.codn t .
+If it is given one or more arguments, and any of them are
+.codn nil ,
+it returns
+.codn nil .
+Otherwise it returns the value of the last argument.
+
+.TP* Examples:
+.cblk
(and) -> t
(and (> 10 5) (stringp "foo")) -> t
- (and 1 2 3) -> 3
-
-.SS Operator/function or
-
-.TP
-Syntax:
-
- (or {<form>}*)
- [or {<arg>}*]
-
-.TP
-Description:
-
-There exist both an or operator and an or function. A list form with the
-symbol or in the fist position is interpreted as an invocation of the
+ (and 1 2 3) -> 3 ;; short-hand for (if (and 1 2) 3).
+.cble
+
+.coNP Operator/function @ or
+.synb
+.mets (or << form *)
+.mets [or << arg *]
+.syne
+.desc
+There exist both an
+.code or
+operator and an
+.code or
+function. A list form with the
+symbol
+.code or
+in the fist position is interpreted as an invocation of the
operator. The function can be accessed using the DWIM bracket notation and in
other ways.
The or operator provides three functionalities in one. It computes the
logical "or" function over several forms. It controls evaluation (a.k.a.
-"short-circuiting"). The behavior of or also provides for a simplified
-selection of the first non-nil value from a sequence of forms.
-
-The or operator evaluates as follows. First, a return value is
-established and initialized to the value nil. The forms, if any,
+"short-circuiting"). The behavior of
+.code or
+also provides an idiom for the selection of the first non-nil value from a
+sequence of forms.
+
+The
+.code or
+operator evaluates as follows. First, a return value is
+established and initialized to the value
+.codn nil .
+The
+.metn form s,
+if any,
are evaluated from left to right. The return value is overwritten
-with the result of each form. Evaluation stops when all forms are
-exhausted, or when a form yields a true value. When evaluation stops, the
-operator yields the return value.
-
-The and function provides no evaluation control; it receives all of its
-arguments fully evaluated. If it is given no arguments, it returns nil.
-If all of its arguments are nil, it also returns nil. Otherwise, it
-returns the value of the first non-nil argument.
-
-.TP
-Examples:
-
+with the result of each
+.metn form .
+Evaluation stops when all forms are
+exhausted, or when a true value is stored into the return value.
+When evaluation stops, the operator yields the return value.
+
+The
+.code or
+function provides no evaluation control; it receives all of its
+arguments fully evaluated. If it is given no arguments, it returns
+.codn nil .
+If all of its arguments are
+.codn nil ,
+it also returns
+.codn nil .
+Otherwise, it
+returns the value of the first argument which isn't
+.codn nil .
+
+.TP* Examples:
+.cblk
(or) -> nil
(or 1 2) -> 1
(or nil 2) -> 2
(or (> 10 20) (stringp "foo")) -> t
-
-.SS Operator unwind-protect
-
-.TP
-Syntax:
-
- (unwind-protect <protected-form> <cleanup-form>*)
-
-.TP
-Description:
-
-The unwind-protect operator evaluates <protected-form> in such a way that no
-matter how the execution of <protected-form> terminates, the <cleanup-form>-s
+.cble
+
+.coNP Operator @ unwind-protect
+.synb
+.mets (unwind-protect < protected-form << cleanup-form *)
+.syne
+.desc
+The
+.cod unwind-protect
+operator evaluates
+.meta protected-form
+in such a way that no matter how the execution of
+.meta protected-form
+terminates, the
+.metn cleanup-form s
will be executed.
-The cleanup forms, however, are not protected. If a cleanup form terminates via
-some non-local jump, the subsequent cleanup forms are not evaluated.
-
-Cleanup forms themselves can "hijack" a non-local control transfer such
-as an exception. If a cleanup form is evaluated during the processing of
-a dynamic control transfer such as an exception, and that cleanup form
+The
+.metn cleanup-form s,
+however, are not protected. If a
+.meta cleanup-form
+terminates via
+some non-local jump, the subsequent
+.metn cleanup-form s
+are not evaluated.
+
+.metn cleanup-form s
+themselves can "hijack" a non-local control transfer such
+as an exception. If a
+.meta cleanup-form
+is evaluated during the processing of
+a dynamic control transfer such as an exception, and that
+.meta cleanup-form
initiates its own dynamic control transfer, the original control transfer
is aborted and replaced with the new one.
-.TP
-Example:
-
- (block foo
- (unwind-protect
- (progn (return-from foo 42)
- (format t "not reached!\en"))
- (format t "cleanup!\en")))
-
-In this example, the protected progn form terminates by returning from
-block foo. Therefore the form does not complete and so the
-output "not reached!" is not produced. However, the cleanup form
-executes, producing the output "cleanup!".
-
-.SS Operator block
-
-.TP
-Syntax:
-
- (block <name> <body-form>*)
-
-.TP
-Description:
-
-The block operator introduces a named block around the execution of
-some forms. The <name> argument must be a symbol. Since a block name is not
+.TP* Example:
+.cblk
+ (block foo
+ (unwind-protect
+ (progn (return-from foo 42)
+ (format t "not reached!\en"))
+ (format t "cleanup!\en")))
+.cble
+
+In this example, the protected
+.code progn
+form terminates by returning from
+block
+.codn foo .
+Therefore the form does not complete and so the
+output
+.str not reached!
+is not produced. However, the cleanup form
+executes, producing the output
+.strn cleanup! .
+
+.coNP Operator @ block
+.synb
+.mets (block < name << body-form *)
+.syne
+.desc
+The
+.code block
+operator introduces a named block around the execution of
+some forms. The
+.meta name
+argument must be a symbol. Since a block name is not
a variable binding, keyword symbols are permitted, and so are the symbols
-t and nil. A block named by the symbol nil is slightly special: it is
+.code t
+and
+.codn nil .
+A block named by the symbol nil is slightly special: it is
understood to be an anonymous block.
Blocks in TXR Lisp have dynamic scope. This means that the following
situation is allowed:
+.cblk
(defun func () (return-from foo 42))
(block foo (func))
+.cble
-The function can return from the foo block even though the foo block
-does not lexically surround foo.
+The function can return from the
+.code foo
+block even though the
+.code foo
+block
+does not lexically surround
+.codn foo .
Thus blocks in TXR Lisp provide dynamic non-local returns, as well
as returns out of lexical nesting.
-.TP
-Dialect Note:
-
+.TP* "Dialect Note:"
In Common Lisp, blocks are lexical. A separate mechanism consisting of
catch and throw operators performs non-local transfer based on symbols.
The TXR Lisp example:
+.cblk
(defun func () (return-from foo 42))
(block foo (func))
+.cble
is not allowed in Common Lisp, but can be transliterated to:
+.cblk
(defun func () (throw 'foo 42))
(catch 'foo (func))
+.cble
Note that foo is quoted in CL. This underscores the dynamic nature of
-the construct. THROW itself is a function and not an operator.
-
-.SS Operators return, return-from
-
-.TP
-Syntax:
-
- (return [<value>])
- (return-from <name> [<value>])
-
-.TP
-Description:
-
-The return operator must be dynamically enclosed within an anonymous
-block (a block named by the symbol nil). It immediately terminates the
+the construct.
+.code throw
+itself is a function and not an operator.
+
+.coNP Operators @ return and @ return-from
+.synb
+.mets (return <> [ value ])
+.mets (return-from < name <> [ value ])
+.syne
+.desc
+The
+.code return
+operator must be dynamically enclosed within an anonymous
+block (a block named by the symbol
+.codn nil ).
+It immediately terminates the
evaluation of the innermost anonymous block which encloses it, causing
it to return the specified value. If the value is omitted, the anonymous
-block returns nil.
-
-The return-from operator must be dynamically enclosed within a named block
-whose name matches the <name> argument. It immediately terminates the
+block returns
+.codn nil .
+
+The
+.code return-from
+operator must be dynamically enclosed within a named block
+whose name matches the
+.meta name
+argument. It immediately terminates the
evaluation of the innermost such block, causing it to return the specified
-value. If the value is omitted, that block returns nil.
-
-.TP
-Example:
+value. If the value is omitted, that block returns
+.codn nil .
+.TP* Example:
+.cblk
(block foo
(let ((a "abc\en")
(b "def\en"))
(pprint a *stdout*)
(return-from foo 42)
(pprint b *stdout*)))
-
-Here, the output produced is "abc". The value of b is not printed
-because the return-from terminates block foo, and so the second pprint
-form is not evaluated.
-
-.SH EVALUATION
-
-.SS Operator dwim
-
-.TP
-Syntax:
-
- (dwim <argument>*)
-
- [<argument>*]
-
-.TP
-Description:
-
-The dwim operator's name is an acronym: DWIM may be taken to mean
+.cble
+
+Here, the output produced is
+.strn "abc" .
+The value of
+.code b
+is not printed
+because.
+.code return-from
+terminates block
+.codn foo ,
+and so the second pprint form is not evaluated.
+
+.SS* Evaluation
+
+.coNP Operator @ dwim
+.synb
+.mets (dwim << argument *)
+.mets <> [ argument *]
+.syne
+.desc
+The
+.code dwim
+operator's name is an acronym: DWIM may be taken to mean
"Do What I Mean", or alternatively, "Dispatch, in a Way that is
Intelligent and Meaningful".
-The notation [...] is a shorthand equivalent to (dwim ...) and is the preferred
-way for writing dwim expressions.
-
-The dwim operator takes a variable number of arguments, which are
+The notation
+.code [...]
+is a shorthand equivalent to
+.code (dwim ...)
+and is usually the preferred way for writing
+.code dwim
+expressions.
+
+The
+.code dwim
+operator takes a variable number of arguments, which are
all evaluated in the same way: the first argument is not evaluated differently
from the remaining arguments.
@@ -6112,27 +10079,35 @@ This means that the first argument isn't a function name, but an ordinary
expression which can simply compute a function object (or, more generally,
a callable object).
-Furthermore, for those arguments of dwim which are symbols (after all
+Furthermore, for those arguments of
+.code dwim
+which are symbols (after all
macro-expansion is performed on the arguments), the evaluation rules are
altered. For the purposes of resolving symbols to values, the function and
variable binding namespaces are considered to be merged into a single space,
creating a situation that is very similar to a Lisp-1 style dialect.
This special Lisp-1 evaluation is not recursively applied. All arguments of
-dwim which, after macro expansion, are not symbols are evaluated using the
+.code dwim
+which, after macro expansion, are not symbols are evaluated using the
normal Lisp-2 evaluation rules. Thus, the DWIM operator must be used
in every expression where the Lisp-1 rules for reducing symbols to
values are desired.
-After macro expansion, the first argument of dwim may not be an operator such
-as let, or the name of a macro. Prior to macroexpansion, any argument of dwim
+After macro expansion, the first argument of
+.code dwim
+may not be an operator such
+as
+.codn let ,
+or the name of a macro. Prior to macroexpansion, any argument of
+.code dwim
may be a symbol macro.
If a symbol has bindings both in the variable and function namespace in scope,
and is referenced by a dwim argument, this constitutes a conflict which is
resolved according to two rules. When nested scopes are concerned, then an
inner binding shadows an outer binding, regardless of their kind. An inner
-variable binding for a symbol X shadows an outer or global function binding,
+variable binding for a symbol shadows an outer or global function binding,
and vice versa.
If a symbol is bound to both a function and variable in the global namespace,
@@ -6140,83 +10115,139 @@ then the variable binding is favored.
Macros do not participate in the special scope conflation. This is apparent
in two ways. Firstly, the space of symbol macros is not folded together with
-the space of regular macros. An argument of dwim that is a symbol might be
+the space of regular macros. An argument of
+.code dwim
+that is a symbol might be
symbol macro, variable or function, but it cannot be interpreted as the name of
a regular macro. Secondly, function bindings cannot shadow symbol macros. If a
function is defined in an inner scope relative to a symbol macro for the
same symbol, that symbol macro still hides the function when it appears in
-a dwim form. Symbol macros are expanded without any consideration for the
-dwim operator, which is not treated specially by the expansion phase.
+a
+.code dwim
+form. Symbol macros are expanded without any consideration for the
+.code dwim
+operator, which is not treated specially by the expansion phase.
(Interaction between dwim and macros may become more sophisticated in the
future.)
-How many arguments are required by the dwim operator depends on the type of
+How many arguments are required by the
+.code dwim
+operator depends on the type of
object to which the first argument expression evaluates. The possibilities
are:
+.RS
+.meIP >> [ function << argument *]
+Call the given function object to the given arguments.
-.IP "[<function> <argument>*]"
-Call the given the function object to the given arguments.
-
-.IP "[<symbol> <argument>*]"
+.meIP >> [ symbol << argument *]
If the first expression evaluates to a symbol, that symbol
is resolved in the function namespace, and then
the resulting function, if found, is called with the
given arguments.
-.IP "[<sequence> <index>]"
-Retrieve an element from <sequence>, given by the integer <index>, given by the
-integer <index>.
+.meIP >> [ sequence << index ]
+Retrieve an element from
+.metn sequence ,
+given by the integer
+.metn index .
The following equivalences hold:
+.cblk
[seq index] <--> (ref seq index)
(set [seq index] new) <--> (refset seq index new)
+.cble
-This form accepts update operators like inc and flip.
+This form accepts update operators like
+.code inc
+and
+.codn flip .
-.IP "[<sequence> <from-index>..<to-below-index>]"
+.meIP >> [ sequence << from-index..to-below-index ]
Retrieve the specified range of elements.
-The range of elements is specified in the car and cdr fields of a cons cell,
-for which the .. (dotdot) syntactic sugar is useful.
+The range of elements is specified in the
+.code car
+and
+.code cdr
+fields of a cons cell,
+for which the
+.code ..
+(dotdot) syntactic sugar is useful.
See the section on Range Indexing below.
The following equivalences hold:
+.cblk
[seq from..to] <--> (sub seq from to)
(set [seq from..to] new) <--> (refset seq new from to)
+.cble
-This form does not accept update operators like inc and flip.
+This form does not accept update operators like
+.code inc
+and
+.codn flip .
-.IP "[<sequence> <index-list>]"
+.meIP >> [ sequence << index-list ]
Elements specified
-by <index-list> are extracted from <sequence> and returned as a sequence
-of the same kind as <sequence>. Equivalent to (select <sequence>
-<where-index>), except when the target of an assignment operation.
+by
+.meta index-list
+are extracted from
+.meta sequence
+and returned as a sequence
+of the same kind as
+.metn sequence .
+This form is equivalent to
+.cblk
+.meti (select < sequence << where-index )
+.cble
+except when the target of an assignment operation.
The following equivalences hold:
+.cblk
[seq list] <--> (select seq list)
(set [seq list] new) <--> (refset seq new list)
-
-This form does not accept update operators like inc and flip.
-
-Note that unlike the select function, this does not support [<hash>
-<index-list>], because since hash keys may be lists, that syntax is
-indistinguishable from a simple hash lookup where <index-list> is the key.
-
-.IP "[<hash> <key> <default-value>]"
-Retrieve a value from the hash table corresponding to <key>,
-or <default-value> if there is no such entry.
-
-The first argument may not be an operator such as let, only a function.
-
-The places denoted by the dwim operator can be assigned. There are some
+.cble
+
+This form does not accept update operators like
+.code inc
+and
+.codn flip .
+
+Note that unlike the select function, this does not support
+.cblk
+.meti >> [ hash << index-list ]
+.cble
+because since hash keys may be lists, that syntax is
+indistinguishable from a simple hash lookup where
+.meta index-list
+is the key.
+
+.meIP >> [ hash < key << default-value ]
+Retrieve a value from the hash table corresponding to
+.metn key ,
+or
+.meta default-value
+if there is no such entry.
+
+The first argument may not be an operator such as
+.codn let ,
+only a function.
+
+The places denoted by the
+.code dwim
+operator can be assigned. There are some
restrictions. List, string and vector ranges can only be replaced using
-the set operator. The other operators like push do not apply.
-Characters in a string can only be assigned with set or incremented with inc
+the set operator. The other operators like
+.code push
+do not apply.
+Characters in a string can only be assigned with
+.code set
+or incremented with
+.code inc
and dec.
The source of a range assignment can be a string, vector or list,
@@ -6224,55 +10255,112 @@ regardless of whether the target is a string, vector or list.
If the target is a string, the replacement sequence must be
a string, or a list or vector of characters.
-.TP
-Range Indexing
+.RE
+.PP
+.TP* "Range Indexing"
Vector and list range indexing is based from zero. The first element element
-zero. Furthermore, the value -1 refers to the last element of the vector or
-list, and -2 to the second last and so forth. So the range 1 .. -2 means
+zero. Furthermore, the value
+.code -1
+refers to the last element of the vector or
+list, and
+.code -2
+to the second last and so forth. So the range
+.code 1 .. -2
+means
"everything except for the first element and the last two".
-The symbol t represents the position one past the end of the vector, string or
-list, so 0 .. t denotes the entire list or vector, and the range t .. t
+The symbol
+.code t
+represents the position one past the end of the vector, string or
+list, so
+.code 0 .. t
+denotes the entire list or vector, and the range
+.code t .. t
represents the empty range just beyond the last element.
-It is possible to assign to t .. t. For instance:
+It is possible to assign to
+.codn t .. t .
+For instance:
+.cblk
(defvar list '(1 2 3))
(set [list t .. t] '(4)) ;; list is now (1 2 3 4)
+.cble
The value zero has a "floating" behavior when used as the end of a range.
If the start of the range is a negative value, and the end of the
range is zero, the zero is interpreted as being the position past the
end of the sequence, rather than the first element. For instance the range
--1..0 means the same thing as -1..t. Zero at the start of a range
-always means the first element, so that 0..-1 refers to all the elements except
-for the last one.
-
-.TP
-Notes:
-
+.code -1..0
+means the same thing as
+.codn -1..t .
+Zero at the start of a range
+always means the first element, so that
+.code 0..-1
+refers to all the elements except for the last one.
+
+.TP* Notes:
The dwim operator allows for a Lisp-1 flavor of programming in TXR Lisp,
which is normally Lisp-2, with some useful extensions.
-A Lisp-1 dialect is one in which an expression like (a b) treats both a and b
-as expressions with the same evaluation rules. The symbols a and b are looked
-up in a variable namespace. A function call occurs if the value of variable
-a is a function object. Thus in a Lisp-1, named functions do not exist as
-such: they are just variable bindings. In a Lisp-1 (car 1 2) means that there
-is a variable called car, which holds a function. In a Lisp-2 (car 1 2) means
-that there is a function called car, and so (car car car) is possible, because
-there can be also a variable called car.
-
-The Lisp-1 design has certain disadvantages, which are avoided in TXR Lisp by
-confining the Lisp-1 expressivity inside the [...] notation, in which operators
-are not allowed. When round parentheses are used, the normal Lisp-2 rules
-apply. A "best of both worlds" situation is achieved. The square brackets
-are just as convenient as parentheses and at the same time visually distinct,
-making it clear that different rules apply.
-
-The Lisp-1 is useful for functional programming, because it eliminates
-occurrences of the call and fun operators. For instance:
+A Lisp-1 dialect is one in which an expression like
+.code (a b)
+treats both a and b
+as expressions subject to the same evaluation rules. This means that the symbols
+.code a
+and
+.code b
+are resolved to values in the same namespace. The form denotes a function call
+occurs if the value of variable
+.code a
+is a function object. Thus in a Lisp-1, named functions do not exist as
+such: they are just variable bindings. In a Lisp-1
+.code (car 1 2)
+means that there
+is a variable called
+.codn car ,
+which holds a function. In a Lisp-2
+.code (car 1 2)
+means that there is a function called
+.codn car ,
+and so
+.code (car car car)
+is possible, because there can be also a variable called
+.code car
+which holds a cons cell object, rather than the
+.code car
+function.
+The Lisp-1 design has a certain disadvantage, namely that it does not integrate
+cleanly with macros. Macros break the Lisp-1 concept that all elements of a
+form are evaluated in the same way. For instance, typical Lisp-1 dialects like
+Scheme have a
+.code let
+operator. So that
+.code (let ((a 1)) ...)
+has the expected meaning. But this expected meaning means that we must
+consider the first position of a compound form specially by checking
+whether it or not it is an operator. In TXR Lisp, this issue is avoided
+entirely, because Lisp-1 semantics are implemented in the
+square bracket notation corresponding to the
+.code dwim
+operator. This notation does not support operators in the leftmost
+position, period: all the positions in the notation are evaluated
+equally, just like the Lisp-1 mantra promises.
+
+Symbol macros do not pose a problem, and so if a symbol macro occurs in the
+first position of a square bracket form, it is treated the same way as in any
+other position.
+
+A "best of both worlds" situation is achieved with the the square brackets.
+They are just as convenient as parentheses and at the same time visually
+distinct, making it clear that different rules apply. Lisp-1 convenience
+is attained, minus the Lisp-1 conceptual problems with macro namespaces.
+
+The Lisp-1 approach is useful for functional programming, because it eliminates
+cluttering occurrences of the call and fun operators. For instance:
+
+.cblk
;; regular notation
(call foo (fun second) '((1 a) (2 b)))
@@ -6280,112 +10368,114 @@ occurrences of the call and fun operators. For instance:
;; [] notation
[foo second '((1 a) (2 b))]
+.cble
Lisp-1 dialects can also provide useful extensions by giving a meaning
to objects other than functions in the first position of a form,
-and the dwim/[...] syntax does exactly this.
-However, unlike Lisp-1 dialects, the [] syntax does not allow operators.
-It
-.B is
-an operator: (dwim ...).
-
-
-.SS Function identity
-
-.TP
-Syntax:
-
- (identity <value>)
-
-.TP
-Description:
-
-The identity function returns its argument.
-
-.TP
-Notes:
-
-The identify function is useful as a functional argument, when a transformation
+and the
+.code dwim/[...]
+syntax does exactly this.
+
+.coNP Function @ identity
+.synb
+.mets (identity << value )
+.syne
+.desc
+The
+.code identity
+function returns its argument.
+
+.TP* Notes:
+The
+.code identity
+function is useful as a functional argument, when a transformation
function is required, but no transformation is actually desired.
-.SS Function eval
-
-.TP
-Syntax:
-
- (eval <form> <env>)
-
-.TP
-Description:
-
-The eval function treats the <form> object as a Lisp expression, which is
+.coNP Function @ eval
+.synb
+.mets (eval < form <> [ env ])
+.syne
+.desc
+The
+.code eval
+function treats the
+.meta form
+object as a Lisp expression, which is
evaluated. The side effects implied by the form are performed, and the value
-which it produces is returned. The <env> object specifies an environment for
+which it produces is returned. The optional
+.meta env
+object specifies an environment for
resolving the function and variable references encountered in the expression.
-The object nil can be specified as an environment, in which case the evaluation
-takes place in the global environment.
-
-See also: the make-env function.
-
-.SS Function make-env
+If this argument is omitted
+.code nil
+then evaluation takes place in the global environment.
-.TP
-Syntax:
-
- (make-env [<variable-bindings> [<function-bindings> [<next-env>]]])
-
-.TP
-Description:
-
-The make-env function creates an environment object suitable as the <env> parameter.
+See also: the
+.code make-env
+function.
-The <variable-bindings> and <function-bindings> parameters, if specified,
+.coNP Function @ make-env
+.synb
+.mets (make-env >> [ variable-bindings >> [ function-bindings <> [ next-env ]]])
+.syne
+.desc
+The
+.code make-env
+function creates an environment object suitable as the
+.code env
+parameter.
+
+The
+.meta variable-bindings
+and
+.meta function-bindings
+parameters, if specified,
should be association lists, mapping symbols to objects. The objects in
-<function-bindings> should be functions, or objects callable as functions.
-
-The <next-env> argument, if specified, should be an environment.
-
-Note: bindings can also be added to an environment using the env-vbind
-and env-fbind functions.
-
-.SS Functions env-vbind and env-fbind
-
-.TP
-Syntax:
-
- (env-vbind <env> <symbol> <value>)
- (env-fbind <env> <symbol> <value>)
-
-.TP
-Description:
-
-These functions bind a symbol to a value in either the function or variable space
-of environment <env>.
+.meta function-bindings
+should be functions, or objects callable as functions.
+
+The
+.meta next-env
+argument, if specified, should be an environment.
+
+Note: bindings can also be added to an environment using the
+.code env-vbind
+and
+.code env-fbind
+functions.
+
+.coNP Functions @ env-vbind and @ env-fbind
+.synb
+.mets (env-vbind < env < symbol << value)
+.mets (env-fbind < env < symbol << value)
+.syne
+.desc
+These functions bind a symbol to a value in either the function or variable
+space of environment
+.codn env .
Values established in the function space should be functions or objects that
can be used as functions such as lists, strings, arrays or hashes.
-If <symbol> already exists in the environment, in the given space, then its
-value is updated with <value>.
-
-.SH MUTATION
-
-.SS Operators inc, dec, set, push, pop, flip and del
-
-.TP
-Syntax:
-
- (inc <place> [<delta>])
- (dec <place> [<delta>])
- (set <place> <new-value>)
- (push <item> <place>)
- (pop <place>)
- (flip <place>)
- (del <place>)
-
-.TP
-Description:
-
+If
+.meta symbol
+already exists in the environment, in the given space, then its
+value is updated with
+.codn value .
+
+.SS* Mutation
+
+.coNP Operators @ inc @ dec @ set @ push @ pop @ flip and @ del
+.synb
+.mets (inc < place <> [ delta ])
+.mets (dec < place <> [ delta ])
+.mets (set < place << new-value )
+.mets (push < item << place )
+.mets (pop << place )
+.mets (flip << place )
+.mets (del << place )
+.syne
+.desc
These destructive operators update the value of a place. A place is a storage
location which is denoted by a form. Place forms are identical to value
accessing forms. That is to say, any form recognized as a place by these
@@ -6401,258 +10491,456 @@ considered part of the program body. Modifying parts of these objects
therefore gives rise to self-modifying code. The behavior of self-modifying
code is not specified.
-The inc and dec update the place by adding or subtracting, respectively, a
-displacement to or from that number. If the <delta> expression is
+The
+.code inc
+and
+.code dec
+update the place by adding or subtracting, respectively, a
+displacement to or from that number. If the
+.meta delta
+expression is
specified, then it is evaluated and its value is used as the increment.
-Otherwise, a default increment of 1 is used. The prior value of the place
-and the delta must be suitable operands for the + and - functions.
-(inc x) is equivalent to (set x (+ 1 x)), except that expression x
-is evaluated only once to determine the storage location. The inc
-and dec operators return the new value that was stored.
-
-The set operator overwrites the previous value of a place with a new value,
+Otherwise, a default increment of
+.code 1
+is used. The prior value of the place
+and the delta must be suitable operands for the
+.code +
+and
+.code -
+functions.
+.code (inc x)
+is equivalent to
+.codn (set x (+ 1 x)) ,
+except that expression x
+is evaluated only once to determine the storage location. The
+.code inc
+and
+.code dec
+operators return the new value that was stored.
+
+The
+.code set
+operator overwrites the previous value of a place with a new value,
and also returns that value.
-The push and pop operators operate on a place which holds a list. The push
+The.
+.code push
+and
+.code pop
+operators operate on a place which holds a list. The
+.code push
operator updates the list by replacing it with a new list which has a new item
at the front, followed by the previous list. The item is returned.
-The pop operator performs the reverse operation: it removes the first item
-from the list and returns it. (push y x) is similar to
-
+The
+.code pop
+operator performs the reverse operation: it removes the first item
+from the list and returns it.
+.code (push y x)
+is similar to
+
+.cblk
(let ((temp y)) (set x (cons temp x)) temp)
+.cble
-except that x is evaluated only once to determine the storage place, and no
-such temporary variable is visible to the program. Similarly, (pop x) is much
-like
+except that
+.code x
+is evaluated only once to determine the storage place, and no
+such temporary variable is visible to the program. Similarly,
+.code (pop x)
+is much like
+.cblk
(let ((temp (car x))) (set x (cdr x)) temp)
-
+.cble
+
except that x is evaluated only once, and no such temporary variable
is visible to the program.
-The flip operator toggles a place between true and false. If the place
-contains a value other than nil, then its value is replaced with nil.
-If it contains nil, it is replaced with t.
-
-The del operator does not modify the value of a place, but rather deletes the
-place itself. Index values and ranges of lists denoted using the dwim operator
+The
+.code flip
+operator toggles a place between true and false. If the place
+contains a value other than
+.codn nil ,
+then its value is replaced with
+.codn nil .
+If it contains
+.codn nil ,
+it is replaced with
+.codn t .
+
+The
+.code del
+operator does not modify the value of a place, but rather deletes the
+place itself. Index values and ranges of lists denoted using the
+.code dwim
+operator
indexing notation can be subject to a deletion, as can hash table entries
-denoted using dwim or gethash. It is an error to try to delete other kinds of
-places such as simple variables. The del operator returns the value of the
+denoted using
+.code dwim
+or
+.codn gethash .
+It is an error to try to delete other kinds of
+places such as simple variables. The
+.code del
+operator returns the value of the
place that was deleted. Deleting from a sequence means removing the element or
elements. Deleting a hash place means removing the corresponding entry from the
hash table.
Currently, these forms are recognized as places:
- <symbol>
-
- (car <cons>)
-
- (cdr <cons>)
-
- (gethash <hash> <key> <default-value>)
-
- (vecref <vector> <index>)
-
- (dwim <obj> ...)
-
- [<obj> ...] ;; equivalent to (dwim <obj> ...)
-
-
-A <symbol> place denotes a variable. If the variable does not exist, it is an
-error.
-
-The (car <form>) and (cdr <form>) places denote the corresponding slots
-of a cons cell. The <cons> form must be an expression which evaluates to a
-cons.
-
-The gethash place denotes a value stored in a hash table.
-The form <hash> must evaluate to a hash table. If the place does not exist
+.meIP < symbol
+A .meta symbol place denotes a variable. If the variable does not exist, it is
+an error.
+
+.meIP (car << cons )
+.meIP (cdr << cons )
+These places denote the corresponding slots
+of a cons cell. The
+.meta cons
+form must be an expression which evaluates to a cons.
+
+.meIP (gethash < hash < key << default-value )
+The
+.code gethash
+place denotes a value stored in a hash table.
+The form
+.meta hash
+must evaluate to a hash table. If the place does not exist
in the hash table under the given key, then the destructive operation
-will create it. In that case, the <default-value> form is evaluated to
+will create it. In that case, the
+.meta default-value
+form is evaluated to
determine the initial value of the place. Otherwise it is ignored.
-The vecref place denotes a vector element, allowing vector elements
+.meIP (vecref < vector> << index )
+The
+.code vecref
+place denotes a vector element, allowing vector elements
to be treated as assignment places.
-The dwim/[] place denotes a vector element, list element, string, or hash
-table, depending on the type of obj.
-
-.SH BINDING AND ITERATION
-
-.SS Operator defvar
-
-.TP
-Syntax:
-
- (defvar <sym> <value>)
-
-.TP
-Description:
-
-The defvar operator binds a variable in the global environment.
-
-If the variable named <sym> already exists in the global environment, the
-form has no effect; the <value> form is not evaluated, and the value of the
+.meIP (dwim < obj ...)
+.meIP >> [ obj ...] ;; equivalent
+The
+.code dwim/[]
+place denotes a vector element, list element, string, or hash
+table, depending on the type of
+.metn obj .
+
+.SS* Binding and Iteration
+.coNP Operator @ defvar
+.synb
+.mets (defvar < sym << value )
+.syne
+
+.desc
+
+The
+.code defvar
+operator binds a variable in the global environment.
+
+If the variable named
+.meta sym
+already exists in the global environment, the
+form has no effect; the
+.meta value
+form is not evaluated, and the value of the
variable is unchanged.
If the variable does not exist, then it is introduced, with a value given by
-evaluating the <value> form. The <value> form is evaluated in the environment
-in which the defvar form occurs, not necessarily in the global environment.
-
-The symbols t and nil may not be used as variables, and neither
+evaluating the
+.meta value
+form. The
+.meta value
+form is evaluated in the environment
+in which the
+.code defvar
+form occurs, not necessarily in the global environment.
+
+The symbols
+.code t
+and
+.code nil
+may not be used as variables, and neither
can be keyword symbols: symbols denoted by a leading colon.
-In addition to creating a binding, the defvar operator also marks <sym>
+In addition to creating a binding, the
+.code defvar
+operator also marks
+.meta sym
as the name of a special variable. This changes what it means to bind
-that symbol in a lexical binding construct such as the let operator,
-or a function parameter list. See the section "Special Variables" far above.
-
-.SS Operators let and let*
-
-.TP
-Syntax:
-
- (let ({<sym> | (<sym> <init-form>)}*) <body-form>*)
- (let* ({<sym> | (<sym> <init-form>)}*) <body-form>*)
-
-.TP
-Description:
-
-The let and let* operators introduce a new scope with variables and
-evaluate forms in that scope. The operator symbol, either let or let*,
+that symbol in a lexical binding construct such as the
+.code let
+operator, or a function parameter list. See the section "Special Variables" far
+above.
+
+.coNP Operators @ let and @ let*
+.synb
+.mets (let >> ({ sym | >> ( sym << init-form )}*) << body-form *)
+.mets (let* >> ({ sym | >> ( sym << init-form )}*) << body-form *)
+.syne
+.desc
+The.
+.code let
+and
+.code let*
+operators introduce a new scope with variables and
+evaluate forms in that scope. The operator symbol, either
+.code let
+or
+.codn let* ,
is followed by a list which can contain any mixture of variable
-name symbols, or (<sym> <init-form>) pairs. A symbol
+name symbols, or
+.cblk
+.meti >> ( sym << init-form )
+.cble
+pairs. A symbol
denotes the name of variable to be instantiated and initialized
-to the value nil. A symbol specified with an init-form denotes
-a variable which is initialized from the value of the init-form.
-
-The symbols t and nil may not be used as variables, and neither
+to the value
+.codn nil .
+A symbol specified with an init-form denotes
+a variable which is initialized from the value of the
+.metn init-form .
+
+The symbols
+.code t
+and
+.code nil
+may not be used as variables, and neither
can be keyword symbols: symbols denoted by a leading colon.
-The difference between let and let* is that in let*, later init-forms
+The difference between
+.code let
+and
+.code let*
+is that in
+.codn let* ,
+later
+.codn init-form s
have visibility over the variables established by earlier variables
-in the same let* construct. In plain let, the variables are not
-visible to any of the init-forms.
-
-When the variables are established, then the body forms
-are evaluated in order. The value of the last form becomes the
-return value of the let.
-
-If the forms are omitted, then the return value nil is produced.
-
-The variable list may be empty.
-
-
-.TP
-Examples:
-
+in the same let* construct. In plain
+.codn let ,
+the variables are not visible to any of the
+.metn init-form s.
+
+When the variables are established, then the
+.metn body-form s
+are evaluated in order. The value of the last
+.meta body-form
+becomes the return value of the
+.codn let .
+
+If there are no
+.metn body-form s,
+then the return value
+.code nil
+is produced.
+
+The list of variables may be empty.
+
+.TP* Examples:
+.cblk
(let ((a 1) (b 2)) (list a b)) -> (1 2)
(let* ((a 1) (b (+ a 1))) (list a b (+ a b))) -> (1 2 3)
(let ()) -> nil
(let (:a nil)) -> error, :a and nil can't be used as variables
-
-.SS Operators for and for*
-
-.TP
-Syntax:
-
- ({for | for*} ({<sym> | (<sym> <init-form>)}*)
- ([<test-form> <result-form>*])
- (<inc-form>*)
- <body-form>*)
-
-.TP
-Description:
-
-The for and for* operators combine variable binding with loop iteration.
+.cble
+
+.coNP Operators @ for and @ for*
+.synb
+.mets >> ({ for | for } >> ({ sym | >> ( sym << init-form )}*)
+.mets \ \ \ \ \ \ \ \ \ \ \ \ \ << ([ test-form << result-form *])
+.mets \ \ \ \ \ \ \ \ \ \ \ \ \ <> ( inc-form *)
+.mets \ \ << body-form *)
+.syne
+.desc
+
+The
+.code for
+and
+.code for*
+operators combine variable binding with loop iteration.
The first argument is a list of variables with optional initializers,
-exactly the same as in the let and let* operators. Furthermore, the
-difference between for and for* is like that between let and let* with
-regard to this list of variables.
-
-The for operators execute these steps:
-
-1. Establish bindings for the specified variables similarly to let
-and let*. The variable bindings are visible over the <test-form>, each
-<result-form>, each <inc-form> and each <body-form>.
-
-2. Establish an anonymous block over the remaining forms, allowing
-the return operator to be used to terminate the loop.
-
-3. Evaluate <test-form>. If <test-form> yields nil, then the loop
-terminates. Each <result-form> is evaluated, and the value of the last of these
-forms is is the result value of the for loop. If there are no <result-form>-s
-then the result value is nil. If the <test-form> is omitted, then the test
+exactly the same as in the
+.code let
+and
+.code let*
+operators. Furthermore, the
+difference between
+.code for
+and
+.code for*
+is like that between
+.code let
+and
+.code let*
+with regard to this list of variables.
+
+The
+.code for
+and
+.code for*
+operators execute these steps:
+.RS
+.IP 1.
+Establish bindings for the specified variables similarly to
+.code let
+and
+.codn let* .
+The variable bindings are visible over the
+.metn test-form ,
+each
+.metn result-form ,
+each
+.meta inc-form
+and each
+.metn body-form .
+.IP 2.
+Establish an anonymous block over the remaining forms, allowing
+the
+.code return
+operator to be used to terminate the loop.
+.IP 3.
+Evaluate
+.metn test-form .
+If
+.meta test-form
+yields
+.codn nil ,
+then the loop terminates. Each
+.meta result-form
+is evaluated, and the value of the last of these
+forms is is the result value of the loop.
+If there are no
+.metn result-form s
+then the result value is
+.codn nil .
+If the
+.meta test-form
+is omitted, then the test
is taken to be true, and the loop does not terminate.
-
-4. Otherwise, if <test-form> yields non-nil, then each <body-form>
-is evaluated in turn. Then, each <inc-form> is evaluated in turn
-and processing resumes at step 2.
-
-Furthermore, the for operators establish an anonymous block,
-allowing the return operator to be used to terminate at any point.
-
-.SS Operators each, each*, collect-each, collect-each*, append-each and append-each*
-
-.TP
-Syntax:
-
- (each ({(<sym> <init-form>)}*) <body-form>*)
- (each* ({(<sym> <init-form>)}*) <body-form>*)
- (collect-each ({(<sym> <init-form>)}*) <body-form>*)
- (collect-each* ({(<sym> <init-form>)}*) <body-form>*)
- (append-each ({(<sym> <init-form>)}*) <body-form>*)
- (append-each* ({(<sym> <init-form>)}*) <body-form>*)
-
-.TP
-Description:
-
-These operator establish a loop for iterating over the elements of one or more
-lists. Each <init-form> must evaluate to a list. The lists are then iterated in
-parallel over repeated evaluations of the <body-form>-s, which each <sym>
+.IP 4.
+Otherwise, if
+.meta test-form
+yields true, then each
+.meta body-form
+is evaluated in turn. Then, each
+.code inc-form
+is evaluated in turn and processing resumes at step 2.
+.RE
+
+Furthermore, the
+.code for
+and
+.code for*
+operators establish an anonymous block,
+allowing the
+.code return
+operator to be used to terminate at any point.
+
+.coNP Operators @, each @, each* @, collect-each @, collect-each* @ append-each and @ append-each*
+.synb
+.mets (each >> ({( sym << init-form )}*) << body-form *)
+.mets (each* >> ({( sym << init-form )}*) << body-form *)
+.mets (collect-each >> ({( sym << init-form )}*) << body-form *)
+.mets (collect-each* >> ({( sym << init-form )}*) << body-form *)
+.mets (append-each >> ({( sym << init-form )}*) << body-form *)
+.mets (append-each* >> ({( sym << init-form )}*) << body-form *)
+.syne
+.desc
+These operators establish a loop for iterating over the elements of one or more
+lists. Each
+.meta init-form
+must evaluate to a list. The lists are then iterated in
+parallel over repeated evaluations of the
+.metn body-form s,
+with each
+.meta sym
variable being assigned to successive elements of its list. The shortest list
-determines the number of iterations, so if any of the <init-form>-s evaluate to
+determines the number of iterations, so if any of the
+.metn init-form s
+evaluate to
an empty list, the body is not executed.
-The body forms are enclosed in an anonymous block, allowing the return
+The body forms are enclosed in an anonymous block, allowing the
+.code return
operator to terminate the loop prematurely and optionally specify
the return value.
-The collect-each and collect-each* variants are like each and each*,
+The
+.code collect-each
+and
+.code collect-each*
+variants are like
+.code each
+and
+.codn each* ,
except that for each iteration, the resulting value of the body is collected
into a list. When the iteration terminates, the return value of the
-collect-each or collect-each* operator is this collection.
-
-The append-each and append-each* variants are like each and each*,
+.code collect-each
+or
+.code collect-each*
+operator is this collection.
+
+The
+.code append-each
+and
+.code append-each*
+variants are like
+.code each
+and
+.codn each* ,
except that for each iteration other than the last, the resulting value of the
body must be a list. The last iteration may produce either an atom or a list.
The objects produced by the iterations are combined together as if they
were arguments to the append function, and the resulting value is the
-value of the append-each or append-each* operator.
-
-The alternate forms denoted by the adorned symbols each*, collect-each* and
-append-each*, variants differ from each, collect-each and append-each* in the
-following way. The plain forms evaluate the <init-form>-s in an environment in
-which none of the <sym> variables are yet visible. By contrast, the alternate
-forms evaluate each <init-form> in an environment in which bindings for the
-previous <sym> variables are visible. In this phase of evaluation, <sym>
+value of the
+.code append-each
+or
+.code append-each*
+operator.
+
+The alternate forms denoted by the adorned symbols
+.codn each* ,
+.code collect-each*
+and
+.codn append-each* ,
+differ from
+.codn each ,
+.code collect-each
+and
+.code append-each*
+in the following way. The plain forms evaluate the
+.metn init-form s
+in an environment in which none of the
+.code sym
+variables are yet visible. By contrast, the alternate
+forms evaluate each
+.meta init-form
+in an environment in which bindings for the
+previous
+.meta sym
+variables are visible. In this phase of evaluation,
+.meta sym
variables are list-valued: one by one they are each bound to the list object
-emanating from their corresponding <init-form>. Just before the first loop
-iteration, however, the <sym> variables are assigned the first item from each
+emanating from their corresponding
+.metn init-form .
+Just before the first loop
+iteration, however, the
+.meta sym
+variables are assigned the first item from each
of their lists.
-.TP
-Examples:
-
+.TP* Example:
+.cblk
;; print numbers from 1 to 10 and whether they are even or odd
- (each* ((n (range 1 10))
- (even (collect-each ((n m)) (evenp m)))) ;; n is a list here
- (format t "~s is ~s\en" n (if even "even" "odd"))) ;; n is an item here
-
- Output:
-
+ (each* ((n (range 1 10)) ;; n list a list here!
+ (even (collect-each ((n m)) (evenp m))))
+ ;; n is an item here!
+ (format t "~s is ~s\en" n (if even "even" "odd")))
+.cble
+.TP* Output:
+.cblk
1 is odd
2 is even
3 is odd
@@ -6663,49 +10951,62 @@ Examples:
8 is even
9 is odd
10 is even
-
-.SH FUNCTION OBJECTS AND NAMED FUNCTIONS
-
-.SS Operator defun
-
-.TP
-Syntax:
-
- (defun <name> (<param>* [: <opt-param>*] [. <rest-param>]) <body-form>*)
-
-Description:
-
-The defun operator introduces a new function in the global function namespace.
+.cble
+
+.SS* Function Objects and Named Functions
+
+.coNP Operator @ defun
+.synb
+.mets (defun < name <> ( param * [: << opt-param *] [. << rest-param ])
+.mets \ \ << body-form )
+.syne
+.desc
+The
+.code defun
+operator introduces a new function in the global function namespace.
The function is similar to a lambda, and has the same parameter syntax
-and semantics as the lambda operator.
+and semantics as the
+.code lambda
+operator.
-Unlike in lambda, the <body-form>-s of a defun are surrounded by a block.
+Unlike in
+.codn lambda ,
+the
+.metn body-form s
+of a
+.code defun
+are surrounded by a block.
The name of this block is the same as the name of the function, making it
-possible to terminate the function and return a value using (return-from <name>
-<value>). For more information, see the definition of the block operator.
+possible to terminate the function and return a value using
+.cblk
+.meti (return-from < name << value ).
+.cble
+For more information, see the definition of the block operator.
A function may call itself by name, allowing for recursion.
-.SS Operator lambda
-
-.TP
-Syntax:
-
- (lambda (<param>* [: <opt-param>*] [. <rest-param>]) {<body-form>}*)
-
- (lambda <rest-param> {<body-form>}*)
-
-.TP
-Description:
-
-The lambda operator produces a value which is a function. Like in most other
+.coNP Operator @ lambda
+.synb
+.mets (lambda <> ( param * [: << opt-param *] [. << rest-param ])
+.mets \ \ << body-form )
+.mets (lambda < rest-param
+.mets \ \ << body-form )
+.syne
+.desc
+The
+.code lambda
+operator produces a value which is a function. Like in most other
Lisps, functions are objects in TXR Lisp. They can be passed to functions as
arguments, returned from functions, aggregated into lists, stored in variables,
et cetera.
-The first argument of lambda is the list of parameters for the function. It
+The first argument of
+.code lambda
+is the list of parameters for the function. It
may be empty, and it may also be an improper list (dot notation) where the
-terminating atom is a symbol other than nil. It can also be a single symbol.
+terminating atom is a symbol other than
+.codn nil .
+It can also be a single symbol.
The second and subsequent arguments are the forms making up the function body.
The body may be empty.
@@ -6715,22 +11016,47 @@ are visible to the body forms. The variables are initialized from the values of
the argument expressions appearing in the function call.
The dotted notation can be used to write a function that accepts
-a variable number of arguments. To write a function that accepts
-variable arguments only, with no required arguments, use a single symbol.
-
-The keyword symbol : (colon) can appear in the parameter list. This is
+a variable number of arguments. There are two ways write a function that
+accepts only a variable argument list and no required arguments:
+
+.cblk
+.mets (lambda (. << rest-param ) ...)
+.mets (lambda < rest-param ...)
+.cble
+
+(These notations are syntactically equivalent because the list notation
+.code (. X)
+actually denotes the object
+.code X
+which isn't wrapped in any list).
+
+The keyword symbol
+.code :
+(colon) can appear in the parameter list. This is
the symbol in the keyword package whose name is the empty string. This
symbol is treated specially: it serves as a separator between
-required parameters and optional parameters. Furthermore, the : symbol
-has a role to play in function calls: it can be specified as an argument
+required parameters and optional parameters. Furthermore, the
+.code :
+symbol has a role to play in function calls: it can be specified as an argument
value to an optional parameter by which the caller indicates that the
optional argument is not being specified. It will be processed exactly
that way.
-An optional parameter can also be written in the form (<name> <expr> [<sym>]).
+An optional parameter can also be written in the form
+.cblk
+.meti >> ( name < expr <> [ sym ]) .
+.cble
In this situation, if the call does not specify a value for the parameter
-(or specifies a value as the keyword : (colon)) then the parameter takes on the
-value of the expression <expr>. If <sym> is specified, then <sym> will be
+(or specifies a value as the keyword
+.code :
+(colon)) then the parameter takes on the
+value of the expression
+.metn expr .
+If
+.meta sym
+is specified, then
+.meta sym
+will be
introduced as an additional binding with a boolean value which indicates
whether or not the optional parameter had been specified by the caller.
@@ -6738,239 +11064,326 @@ The initializer expressions are evaluated an environment in which
all of the previous parameters are visible, in addition to the surrounding
environment of the lambda. For instance:
+.cblk
(let ((default 0))
(lambda (str : (end (length str)) (counter default))
(list str end counter)))
-
-In this lambda, the initializing expression for the optional parameter
-end is (length str), and the str variable it refers to is the previous
+.cble
+
+In this
+.codn lambda ,
+the initializing expression for the optional parameter
+end is
+.codn (length str) ,
+and the
+.code str
+variable it refers to is the previous
argument. The initializer for the optional variable counter is
the expression default, and it refers to the binding established
by the surrounding let. This reference is captured as part of the
-lambda's lexical closure.
-
-.TP
-Examples:
-
-Counting function. This function, which takes no arguments, captures the
-variable "counter". Whenever this object is called, it increments the counter
-by 1 and returns the incremented value.
+.codn lambda 's
+lexical closure.
+.TP* Examples:
+.IP "Counting function:"
+This function, which takes no arguments, captures the
+variable
+.codn counter .
+Whenever this object is called, it increments
+.code counter
+by
+.code 1
+and returns the incremented value.
+
+.cblk
(let ((counter 0))
(lambda () (inc counter)))
+.cble
-Function that takes two or more arguments. The third and subsequent arguments
-are aggregated into a list passed as the single parameter z:
+.IP "Function that takes two or more arguments:"
+The third and subsequent arguments are aggregated into a list passed as the
+single parameter
+.codn z :
+.cblk
(lambda (x y . z) (list 'my-arguments-are x y z))
+.cble
-Variadic function:
+.IP "Variadic function:"
+.cblk
(lambda args (list 'my-list-of-arguments args))
+.cble
-Optional arguments:
+.IP "Optional arguments:"
+.cblk
[(lambda (x : y) (list x y)) 1] -> (1 nil)
[(lambda (x : y) (list x y)) 1 2] -> (1 2)
-
-.SS Function call
-
-.TP
-Syntax:
-
- (call <function> <argument>*)
-
-.TP
-Description:
-
-The call function invokes <function>, passing it the given
-arguments, if any.
-
-.TP
-Examples:
-
-Apply arguments 1 2 to a lambda which adds them to produce 3:
-
-(call (lambda (a b) (+ a b)) 1 2) -> 3
-
-Useless use of call on a named function; equivalent to (list 1 2):
-
-(call (fun list) 1 2) -> (1 2)
-
-.SS Operator fun
-
-.TP
-Syntax:
-
- (fun <function-name>)
-
-.TP
-Description:
-The fun operator retrieves the function object corresponding to a named
+.cble
+
+.coNP Function @ call
+
+.synb
+.mets (call < function << argument *)
+.syne
+.desc
+The
+.code call
+function invokes
+.metn function ,
+passing it the given arguments, if any.
+
+.TP* Examples:
+Apply arguments
+.code 1 2
+to a
+.code lambda
+which adds them to produce
+.codn 3 :
+
+.cblk
+ (call (lambda (a b) (+ a b)) 1 2)
+.cble
+
+Useless use of
+.code call
+on a named function; equivalent to
+.codn (list 1 2) :
+
+.cblk
+ (call (fun list) 1 2)
+.cble
+
+.coNP Operator @ fun
+.synb
+.mets (fun << function-name )
+.syne
+.desc
+The
+.code fun
+operator retrieves the function object corresponding to a named
function in the current lexical environment.
-The <function-name> is a symbol denoting a named function: a built in
-function, or one defined by defun.
-
-Note: the fun operator does not see macro bindings. It is possible to
-retrieve a global macro expander using symbol-function.
-
-.TP
-Dialect Note:
-A lambda expression is not a function name in TXR Lisp. The
-syntax (fun (lambda ...)) is invalid.
-
-.SS Functions symbol-function and symbol-value
-
-.TP
-Syntax:
-
- (symbol-function <symbol>)
- (symbol-value <symbol>)
-
-.TP
-Description:
-
-The symbol-function retrieves the value of the global function binding of the
-given symbol if it has one: that is, the function object tied to the symbol. If
-the symbol has no global function binding, then the value of the global macro
+The
+.meta function-name
+is a symbol denoting a named function: a built in
+function, or one defined by
+.codn defun .
+
+Note: the
+.code fun
+operator does not see macro bindings. It is possible to
+retrieve a global macro expander using
+.codn symbol-function .
+
+.TP* "Dialect Note:"
+A lambda expression is not a function name in TXR Lisp. The
+syntax
+.code (fun (lambda ...))
+is invalid.
+
+.coNP Functions @ symbol-function and @ symbol-value
+.synb
+.mets (symbol-function << symbol )
+.mets (symbol-value << symbol )
+.syne
+.desc
+
+The
+.code symbol-function
+function retrieves the value of the global function binding of the
+given
+.meta symbol
+if it has one: that is, the function object bound to the
+.metn symbol .
+If
+.meta symbol
+has no global function binding, then the value of the global macro
binding is returned. If that doesn't exist, then the value of a global special
-operator binding is returned, and if that doesn't exist, then nil is returned.
+operator binding is returned, and if that doesn't exist, then
+.code nil
+is returned.
-The symbol-value retrieves the value of a global variable, if it exists,
-otherwise nil.
+The
+.code symbol-value
+function retrieves the value of a global variable, if it exists,
+otherwise
+.codn nil .
Note: a function binding is a function, but a macro or special operator binding
binding isn't. The value of a macro binding is a list of the following form:
- (#<environment object> <macro-parameter-list> <body-form>*)
+.cblk
+.mets (#<environment object> < macro-parameter-list << body-form *)
+.cble
The value of a special operator binding is a "C pointer" object, whose
printed representation looks like:
+.cblk
#<cptr: 808be4f>
+.cble
These details may change in future version of TXR.
-.TP
-Dialect note:
-
-Forms which call symbol-function or symbol-value are currently not an
-assignable place. Only the defun operator defines functions, and the set
-operator modifies variables.
-
-.SS Functions boundp and fboundp
-
-.TP
-Syntax:
-
- (boundp <symbol>)
- (fboundp <symbol>)
-
-.TP
-Description:
-
-boundp returns t if the symbol has a variable binding in the global
-environment, otherwise nil.
-
-Foundp returns t if the symbol has a function or macro binding in the global
-environment, or if it is an operator, otherwise nil.
-
-.SS Function func-get-form
-
-.TP
-Syntax:
-
- (func-get-form <func>)
-
-.TP
-Description:
-
-The func-get-form function retrieves a source code form of <func>, which
-must be an interpreted function. The source code form has the syntax
-(<name> <arglist> {<body-form>}*).
-
-.SS Function func-get-env
-
-.TP
-Syntax:
-
- (func-get-env <func>)
-
-.TP
-Description:
-
-The func-get-env function retrieves the environment object associated with
-function <func>. The environment object holds the captured bindings of a
+.TP* "Dialect note:"
+Forms which call
+.code symbol-function
+or
+.code symbol-value
+are currently not assignable places. Only the
+.code defun
+operator defines functions.
+
+.coNP Functions @ boundp and @ fboundp
+.synb
+.mets (boundp << symbol )
+.mets (fboundp << symbol )
+.syne
+.desc
+.code boundp
+returns
+.code t
+if the symbol has a variable binding in the global
+environment, otherwise
+.codn nil .
+
+.code fboundp
+returns
+.code t
+if the symbol has a function or macro binding in the global
+environment, or if it is an operator, otherwise
+.codn nil .
+
+.coNP Function @ func-get-form
+.synb
+.mets (func-get-form << func )
+.syne
+.desc
+
+The
+.code func-get-form
+function retrieves a source code form of
+.metn func ,
+which must be an interpreted function. The source code form has the syntax
+.cblk
+.meti >> ( name < arglist << body-form *) .
+.cble
+
+.coNP Function @ func-get-env
+.synb
+.mets (func-get-env << func )
+.syne
+.desc
+The
+.code func-get-env
+function retrieves the environment object associated with
+function
+.metn func .
+The environment object holds the captured bindings of a
lexical closure.
-.SS Function functionp
-
-.TP
-Syntax:
-
- (functionp <obj>)
-
-.TP
-Description:
-
-The functionp function returns t if <obj> is a function, otherwise it
-returns nil.
-
-.SS Function interp-fun-p
-
-.TP
-Syntax:
-
- (interp-fun-p <obj>)
-
-.TP
-Description:
-
-The interp-fun-p function returns t if <obj> is an interpreted function,
-otherwise it returns nil.
-
-.SS Macros flet and labels
-
-.TP
-Syntax:
-
- (flet ({(<name> <param-list> <function-body-form>*)}*)
- <body-form>*)
-
- (labels ({(<name> <param-list> <function-body-form>*)}*)
- <body-form>*)
-
-.TP
-Description:
-
-The flet and labels macros bind local, named functions in the lexical scope.
-The difference between flet and labels is that a function defined by labels can
-see itself, and therefore recurse directly by name. Moreover, if multiple
+.coNP Function @ functionp
+.synb
+.mets (functionp << obj )
+.syne
+.desc
+
+The
+.code functionp
+function returns
+.code t
+if
+.meta obj
+is a function, otherwise it returns
+.codn nil .
+
+.coNP Function @ interp-fun-p
+.synb
+.mets (interp-fun-p << obj )
+.syne
+.desc
+
+The
+.code interp-fun-p
+function returns
+.code t
+if
+.meta obj
+is an interpreted function, otherwise it returns
+.codn nil .
+
+.coNP Macros @ flet and @ labels
+.synb
+.mets (flet >> ({( name < param-list << function-body-form *)}*)
+.mets \ \ << body-form *)
+
+.mets (labels >> ({( name < param-list << function-body-form *)}*)
+.mets \ \ << body-form *)
+.syne
+.desc
+The
+.code flet
+and
+.code labels
+macros bind local, named functions in the lexical scope.
+The difference between
+.code flet
+and
+.code labels
+is that a function defined by
+.code labels
+can see itself, and therefore recurse directly by name. Moreover, if multiple
functions are defined by the same labels construct, they all see each other.
-By contrast, a flet function does not have itself in scope and cannot recurse.
-Multiple functions in the same flet do not have each other in scope.
-
-More formally, the <function-body-form>-s and <param-list> of the functions
-defined by labels are in a scope in which all of the function names being
-defined by that labels construct are visible.
-
-Under both labels and flet, the local functions that are defined are
-lexically visible to the main <body-form>s.
-
-Note that labels and flat are properly scoped with regard to macros.
-During macro expansion, they shadow, macros defined by macrolet and defmacro.
-
-See also: the macrolet operator.
-
-.TP
-Examples:
+By contrast, a
+.codn flet -defined
+function does not have itself in scope and cannot recurse.
+Multiple functions in the same
+.code flet
+do not have each other's names in their scopes.
+
+More formally, the
+.metn function-body-form -s
+and
+.meta param-list
+of the functions defined by
+.code labels
+are in a scope in which all of the function
+names being defined by that same
+.code labels
+construct are visible.
+
+Under both
+.code labels
+and
+.codn flet ,
+the local functions that are defined are
+lexically visible to the main
+.metn xbody-form .
+
+Note that
+.code labels
+and
+.code flet
+are properly scoped with regard to macros.
+During macro expansion, they shadow, macros defined by
+.code macrolet
+and
+.codn defmacro .
+
+See also: the
+.code macrolet
+operator.
+.TP* Examples:
+.cblk
;; Wastefully slow algorithm for determining even-ness.
;; Note:
;; - mutual recursion between labels-defined functions
- ;; - inner is-even bound by labels shadows the outer one bound by defun
- ;; so the (is-even n) call goes to the local function.
+ ;; - inner is-even bound by labels shadows the outer
+ ;; one bound by defun so the (is-even n) call goes
+ ;; to the local function.
(defun is-even (n)
(labels ((is-even (n)
@@ -6978,98 +11391,90 @@ Examples:
(is-odd (n)
(if (zerop n) nil (is-even (- n 1)))))
(is-even n)))
+.cblk
-.SH OBJECT TYPE AND EQUIVALENCE
-
-.SS Function typeof
-
-.TP
-Syntax:
-
- (typeof <value>)
+.SS* Object Type And Equivalence
+.coNP Function @ typeof
+.synb
+.mets (typeof << value )
+.syne
+.desc
+The
+.code typeof
+function returns a symbol representing the type of
+.metn value .
-.TP
-Description
-
-The typeof function returns a symbol representing the type of <value>.
-
-.RS
+The core types are identified by the following symbols:
-The core types are identified by the following symbols.
-.IP cons
-
-A cons cell.
-
-.IP str
+.coIP cons
+Cons cell.
+.coIP str
String.
-.IP lit
-
-A literal string embedded in the TXR executable image.
-
-.IP chr
+.coIP lit
+Literal string embedded in the TXR executable image.
+.coIP chr
Character.
-.IP fixnum
-
-Fixnum integer. An integer that fits into the value word, not having to
+.coIP fixnum
+Fixnum integer: an integer that fits into the value word, not having to
be heap allocated.
-.IP sym
-
+.coIP sym
Symbol.
-.IP pkg
-
+.coIP pkg
Symbol package.
-.IP fun
-
+.coIP fun
Function.
-.IP vec
-
+.coIP vec
Vector.
-.IP lcons
-
+.coIP lcons
Lazy cons.
-.IP lstr
-
+.coIP lstr
Lazy string.
-.IP env
-
+.coIP env
Function/variable binding environment.
-.IP bignum
-
+.coIP bignum
A bignum integer: arbitrary precision integer that is heap-allocated.
-
.PP
-There are additional kinds of objects, such as streams.
-
-.SS Functions null, not, false
-.TP
-Syntax:
-
- (null <value>)
- (not <value>)
- (false <value>)
-
-.TP
-Description:
-
-The null, not and false functions are synonyms. They tests whether <value> is
-the object nil. They return t if this is the case, nil otherwise.
-
-.TP
-Examples:
+There are additional kinds of objects, such as streams.
+.coNP Functions @, null @, not and @ false
+.synb
+.mets (null << value )
+.mets (not << value )
+.mets (false << value )
+.syne
+.desc
+
+The
+.codn null ,
+.code not
+and
+.code false
+functions are synonyms. They tests whether
+.meta value
+is
+the object
+.codn nil .
+They return
+.code t
+if this is the case,
+.code nil
+otherwise.
+
+.TP* Examples:
+.cblk
(null '()) -> t
(null nil) -> t
(null ()) -> t
@@ -7080,340 +11485,624 @@ Examples:
(let ((list '(b c d)))
(if (not (memq 'a list))
(format t "list ~s does not contain the symbol a\en")))
-
-.SS Function true
-
-.TP
-Syntax:
-
- (true <value>)
-
-.TP
-Description:
-
-The true function is the complement of the null, not and false functions.
-It return t if the <value> is any object other than nil. If <value> is
-nil, it returns nil.
+.cble
+
+.coNP Function @ true
+.synb
+.mets (true << value )
+.syne
+.desc
+
+The
+.code true
+function is the complement of the
+.codn null ,
+.code not
+and
+.code false
+functions.
+
+It return
+.code t
+if the
+.meta value
+is any object other than
+.codn nil .
+If
+.meta value
+is
+.codn nil ,
+it returns
+.codn nil .
Note: programs should avoid explicitly testing values with true.
-For instance (if x ...) should be favored over (if (true x) ...)
-
-.TP
-Example:
-
- ;; Compute indices where the list '(1 nil 2 nil 3) has true values:
- ;; "Where is (1 nil 2 nil 3) true?"
-
+For instance
+.code (if x ...)
+should be favored over
+.codn (if (true x) ...) .
+
+.TP* Example:
+.cblk
+ ;; Compute indices where the list '(1 nil 2 nil 3)
+ ;; has true values:
[where '(1 nil 2 nil 3) true] -> (1 3)
-
-.SS Functions eq, eql and equal
-
-.TP
-Syntax:
-
- (eq <left-obj> <right-obj>)
- (eql <left-obj> <right-obj>)
- (equal <left-obj> <right-obj>)
-
-.TP
-Description:
-
-The principal equality test functions eq, eql and equal test whether
-two objects are equivalent, using different criteria. They return t
-if the objects are equivalent, and nil otherwise.
-
-The eq function uses the strictest equivalence test, called implementation
-equality. The eq function returns t if, and only if, <left-obj> and
-<right-obj> are actually the same object. The eq test is is implemented
+.cble
+
+.coNP Functions @, eq @ eql and @ equal
+.synb
+.mets (eq < left-obj << right-obj )
+.mets (eql < left-obj << right-obj )
+.mets (equal < left-obj << right-obj )
+.syne
+.desc
+The principal equality test functions
+.codn eq ,
+.code eql
+and
+.code equal
+test whether two objects are equivalent, using different criteria. They return
+.code t
+if the objects are equivalent, and
+.code nil
+otherwise.
+
+The
+.code eq
+function uses the strictest equivalence test, called implementation
+equality. The eq function returns
+.code t
+if, and only if,
+.meta left-obj
+and
+.meta right-obj
+are actually the same object. The
+.code eq
+test is is implemented
by comparing the raw bit pattern of the value, whether or not it is
-an immediate value or a pointer to a heaped object, including its type
-tags. Consequently, two objects of different type are never equal, two
-character values are eq if they are the same character, and two fixnum integers
-are eq if they have the same value. All other objects kinds are actually
-represented as pointers, and are eq if they point to the same object in memory.
-So two bignum integers might not be eq even if they have the same numeric
-value, two lists might not be eq even if all their corresponding elements are
-eq, two strings might not be eq even if they hold identical text, etc.
-
-The eql function is slightly less strict than eq. The difference between
-eql and eq is that if <left-obj> and <right-obj> are bignums which have
-the same numeric value, eql returns t, even if they are different objects.
-For all other objects, eql behaves like eq.
-
-The equal function is less strict than eql. In general, it recurses into some
-kinds of aggregate objects to perform a structural equivalence.
-
-If <left-obj> and <right-obj> are eql then they are also equal.
-
-If the two objects are both cons cells, then they are equal if their "car"
-fields are equal and their "cdr" fields are equal.
-
-If two objects are vectors, they are equal if they have the same length, and
-their corresponding elements are equal.
-
-If two objects are strings, they are equal if they are textually identical.
-
-If two objects are functions, they are equal if they have equal environments,
-and if they have equal functions. Two compiled functions are the same if they
-are the same function. Two interpreted functions are equal if their list
-structure is equal.
-
-Two hashes are equal if they use the same equality (both are equal-based,
-or both are the default eql-based), if their user-data elements are equal, if
-their sets of keys are identical, and if the data items associated with
-corresponding keys from each respective hash are equal objects.
+an immediate value or a pointer to a heaped object.
+Two character values are
+.code eq
+if they are the same character, and two fixnum integers
+are
+.code eq
+if they have the same value. All other object representations are actually
+pointers, and are
+.code eq
+if, and only, if they point to the same object in memory.
+So, for instance, two bignum integers might not be
+.code eq
+even if they have the same numeric
+value, two lists might not be
+.code eq
+even if all their corresponding elements are
+.code eq
+and two strings might not be eq even if they hold identical text.
+
+The.
+.code eql
+function is slightly less strict than
+.codn eq .
+The difference between
+.code eql
+and
+.code eq
+is that if
+.meta left-obj
+and
+.meta right-obj
+are numbers which are of the same kind and have the same numeric value,
+.code eql
+returns
+.metn t ,
+even if they are different objects.
+Note that an integers and a floating-point number are not
+.code eql
+even if one has a value which converts to the other: thus,
+.code (eql 0.0 0)
+yields
+.codn nil ;
+the comparison operation which finds these numbers equal is the
+.codn (= 0.0 0) .
+For all other object types,
+.code eql
+behaves like
+.codn eq .
+
+The
+.code equal
+function is less strict still than
+.codn eql .
+In general, it recurses into some
+kinds of aggregate objects to perform a structural equivalence check.
+
+Firstly, if
+.meta left-obj
+and
+.meta right-obj
+are
+.code eql
+then they are also
+.codn equal ,
+though of course the converse isn't necessarily the case.
+
+If two objects are both cons cells, then they are equal if their
+.code car
+fields are
+.code equal
+and their
+.code cdr
+fields are
+.codn equal .
+
+If two objects are vectors, they are
+.code equal
+if they have the same length, and
+their corresponding elements are
+.codn equal .
+
+If two objects are strings, they are equal if they are textually identical.
+
+If two objects are functions, they are
+.code equal
+if they have
+.code equal
+environments,
+and if they have
+the same code. Two compiled functions are considered to have
+the same code if and only if they are pointers to the same function.
+Two interpreted functions are considered to have the same
+code if their list
+structure is
+.codn equal .
+
+Two hashes are
+.code equal
+if they use the same equality (both are
+.codn :equal-based ,
+or both are the default
+.codn :eql-based ),
+if their associated user data elements are equal (see the function
+.codn get-hash-userdata ),
+if their sets of keys are identical, and if the data items associated with
+corresponding keys from each respective hash are
+.code equal
+objects.
For some aggregate objects, there is no special semantics. Two arguments
-which are symbols, packages, or streams are equal if and only if they
-are the same object.
-
-Certain object types have a custom equal function.
-
-.SH BASIC LIST LIBRARY
-
-When the first element of a compound form is a symbol denoting a function,
-the evaluation takes place as follows. The remaining forms, if any, denote
-the arguments to the function. They are evaluated in left to right order
-to produce the argument values, and passed to the function.
-An exception is thrown if there are not enough arguments, or too many.
-
-Programs can define named functions with the defun operator
-
-The following are Lisp functions and variables built-in to TXR.
-
-.SS Function cons
-
-.TP
-Syntax:
-
- (cons <car-value> <cdr-value>)
+which are symbols, packages, or streams are
+.code equal
+if and only if they are the same object.
-.TP
-
-Description:
-
-The cons function allocates, initializes and returns a single cons cell.
-A cons has two fields called "car" and "cdr", which are accessed by
-functions of the same name, or by the functions "first" and "rest",
-which are alternative spellings.
+Certain object types have a custom
+.code equal
+function.
-Lists are made up of conses. A (proper) list is either the symbol nil
+.SS* Basic List Library
+.coNP Function @ cons
+.synb
+.mets (cons < car-value << cdr-value )
+.syne
+.desc
+The
+.code cons
+function allocates, initializes and returns a single cons cell.
+A cons cell has two fields called
+.code car
+and
+.codn cdr ,
+which are accessed by
+functions of the same name, or by the functions
+.code first
+and
+.codn rest ,
+which are synonyms for these.
+
+Lists are made up of conses. A (proper) list is either the symbol
+.code nil
denoting an empty list, or a cons cell which holds the first item of
-the list in its "car", and the list of the remaining items in "cdr".
-(cons 1 nil) allocates a one element list denoted (1). The "cdr"
-is nil, so there are no additional items.
-
-A cons cell with a "cdr" other than nil is printed with the dotted
-pair notation. For example (cons 1 2) yields (1 . 2).
-The notation (1 . nil) is valid as input into the machine,
-but is printed as (1).
-
-A list terminated by an atom other than nil is called an improper
+the list in its
+.codn car ,
+and the list of the remaining items in
+.codn cdr .
+The expression
+.code (cons 1 nil)
+allocates and returns a single cons cell which denotes the one-element
+list
+.codn (1) .
+The
+.code cdr
+is
+.codn nil ,
+so there are no additional items.
+
+A cons cell whose
+.code cdr
+is an atom other than
+.code nil
+is printed with the dotted
+pair notation. For example the cell produced by
+.code (cons 1 2)
+is denoted
+.codn (1 . 2) .
+The notation
+.code (1 . nil)
+is perfectly valid as input, but the cell which it denotes
+will print back as
+.codn (1) .
+The notations are equivalent.
+
+The dotted pair notation can be used regardless of what type
+of object is the cons cell's
+.codn cdr .
+so that for instance
+.code (a . (b c))
+denotes the cons cell whose
+.code car
+is the symbol a
+.code a
+and whose
+.code cdr
+is the list
+.codn (b c) .
+This is eactly the same thing as
+.codn (a b c) .
+In other words
+.code (a b ... l m . (n o ... w . (x y z)))
+is exactly the same as
+.codn (a b ... l m n o ... w x y z).
+
+Every list, and more generally cons cell tree structure, can be written
+in a "fully dotted" notation, such that there are as many dots as there
+are cells. For instance the cons structure of the nested list
+.code (1 (2) (3 4 (5)))
+can be made more explicit using
+.codn (1 . ((2 . nil) . ((3 . (4 . ((5 . nil) . nil))) . nil)))) .
+The structure contains eight conses, and so there are eight dots
+in the fully dotted notation.
+
+The number of conses in a linear list like
+.code (1 2 3)
+is simply the number of items, so that list in particular is
+made of three conses. Additional nestings require additional conses,
+so for instance
+.code (1 2 (3))
+requires four conses. A visual way to count the conses from the printed
+representation is to count the atoms, then add the count of open parentheses,
+and finally subtract one.
+
+A list terminated by an atom other than
+.code nil
+is called an improper
list, and the dot notation is extended to cover improper lists.
-For instance (1 2 . 3) is an improper list of two elements,
-terminated by 3, and can be constructed using (cons 1 (cons 2 3)).
-Another notation for this list is (1 . (2 . 3))
-The list (1 2) is (1 . (2 . nil)).
-
-.SS Function atom
-
-.TP
-Syntax:
-(atom <value>)
-
-.TP
-Description:
-
-The atom function tests whether <value> is an atom. It returns t if this is the
-case, nil otherwise. All values which are not cons cells are atoms.
-
-(atom x) is equivalent to (not (consp x)).
-
-.TP
-Examples:
-
+For instance
+.code (1 2 . 3)
+is an improper list of two elements,
+terminated by
+.codn 3 ,
+and can be constructed using
+.codn (cons 1 (cons 2 3)) .
+The fully dotted notation for this list is
+.codn (1 . (2 . 3)) .
+
+.coNP Function @ atom
+.synb
+.mets (atom << value )
+.syne
+.desc
+The
+.code atom
+function tests whether
+.meta value
+is an atom. It returns
+.code t
+if this is the
+case,
+.code nil
+otherwise. All values which are not cons cells are atoms.
+
+.code (atom x)
+is equivalent to
+.codn (not (consp x)) .
+
+.TP* Examples:
+.cblk
(atom 3) -> t
(atom (cons 1 2)) -> nil
(atom "abc") -> t
(atom '(3)) -> nil
-
-.SS Function consp
-
-.TP
-Syntax:
-
-(consp <value>)
-
-.TP
-Description:
-
-The atom function tests whether <value> is a cons. It returns t if this is the
-case, nil otherwise.
-
-(consp x) is equivalent to (not (atom x)).
-
-Non-empty lists test positive under consp because a list is represented
-as a reference to the first cons in a chain of one or more conses.
-
-Note that a lazy cons is a cons and satisfies the consp test. See the function
-make-lazy-cons.
-
-.TP
-Examples:
-
+.cble
+
+.coNP Function @ consp
+.synb
+.mets (consp << value )
+.syne
+.desc
+The
+.code consp
+function tests whether
+.meta value
+is a cons. It returns
+.code t
+if this is the
+case,
+.code nil
+otherwise.
+
+.code (consp x)
+is equivalent to
+.codn (not (atom x)) .
+
+Non-empty lists test positive under
+.code consp
+because a list is represented as a reference to the first cons in a chain of
+one or more conses.
+
+Note that a lazy cons is a cons and satisfies the
+.code consp
+test. See the function
+.codn make-lazy-cons .
+
+.TP* Examples:
+.cblk
(consp 3) -> nil
(consp (cons 1 2)) -> t
(consp "abc") -> nil
(consp '(3)) -> t
+.cble
+
+.coNP Functions @ car and @ first
+.synb
+.mets (car << object )
+.mets (first << object )
+.syne
+.desc
+The functions
+.code car
+and
+.code first
+are synonyms.
-.SS Functions car and first
-
-.TP
-Syntax:
-
- (car <cons-or-nil>)
- (first <cons-or-nil>)
-
-.TP
-Description:
-
-The functions car and first are synonyms. They retrieve the "car"
-field of a cons cell. (car (cons 1 2)) yields 1.
-
-For programming convenience, (car nil) is allowed, and returns nil,
-even though nil isn't a cons and doesn't have a "car" field.
-
-.SS Functions cdr and rest
-
-.TP
-Syntax:
-
- (cdr <cons-or-nil>)
- (rest <cons-or-nil>)
-
-.TP
-Description:
-
-The functions cdr and rest are synonyms. They retrieve the "cdr"
-field of a cons cell. (cdr (cons 1 2)) yields 2.
-
-For programming convenience, (cdr nil) is allowed, and returns nil,
-even though nil isn't a cons and doesn't have a "cdr" field.
+If
+.meta obejct
+is a cons cell, these functions retrieve the
+.code car
+field of that cons cell.
+.code (car (cons 1 2))
+yields
+.codn 1 .
+
+For programming convenience,
+.meta object
+may be of several other kinds in addition to conses.
+
+.code (car nil)
+is allowed, and returns
+.codn nil .
+
+.meta object
+may also be a vector or a string. If it is an empty vector or
+string, then
+.code nil
+is returned. Otherwise the first character of the string or
+first element of the vector is returned.
+
+.coNP Functions @ cdr and @ rest
+.synb
+.mets (cdr << object )
+.mets (rest << object )
+.syne
+.desc
+The functions
+.code cdr
+and
+.code rest
+are synonyms.
-.TP
+If
+.meta obejct
+is a cons cell, these functions retrieve the
+.code cdr
+field of that cons cell.
+.code (cdr (cons 1 2))
+yields
+.codn 2 .
+
+For programming convenience,
+.meta object
+may be of several other kinds in addition to conses.
+
+.code (cdr nil)
+is allowed, and returns
+.codn nil .
+
+.meta object
+may also be a vector or a string. If it is a non-empty string or vector
+containing at least two items, then the remaining part of the object is
+returned, with the first element removed. For example
+.code (cdr "abc")
+yields
+.codn "bc" .
+If
+.meta object
+is is a one-element vector or string, or an empty vector or string,
+then
+.code nil
+is returned. Thus
+.code (cdr "a")
+and
+.code (cdr "")
+both result in
+.codn nil .
+
+.TP*
Example:
-Walk every element of the list (1 2 3):
+Walk every element of the list
+.code (1 2 3)
+using a
+.code for
+loop:
+.cblk
(for ((i '(1 2 3))) (i) ((set i (cdr i)))
(print (car i) *stdout*)
(print #\enewline *stdout*))
+.cble
-The variable i marches over the cons cells which make up the "backbone"
-of the list. The elements are retrieved using the car function.
-Advancing to the next cell is achieved using (cdr i). If i is the
-last cell in a (proper) list, (cdr i) yields nil. The guard
-expression i fails and the loop terminates.
-
-.SS Functions rplaca and rplacd
-
-.TP
-Syntax:
-
- (rplaca <cons> <new-car-value>)
- (rplacd <cons> <new-cdr-value>)
-
-.TP
-Description:
-
-The rplaca and rplacd functions assign new values into the "car"
-and "cdr" fields of the cell <cons>. Note that (rplaca x y)
-is the same as the more generic (set (car x) y), and likewise
-(rplacd x y) can be written as (set (cdr x) y).
-
-It is an error if <cons> is not a cons or lazy cons. In particular,
-whereas (car nil) is correct, (rplaca nil ...) is erroneous.
-
-The rplaca and rplacd functions return <cons>.
+The variable
+.code i
+marches over the cons cells which make up the "backbone"
+of the list. The elements are retrieved using the
+.code car
+function.
+Advancing to the next cell is achieved using
+.codn (cdr i) .
+If
+.code i
+is the
+last cell in a (proper) list,
+.code (cdr i)
+yields
+.code nil
+and so
+.code i
+becomes
+.codn nil ,
+the loop guard expression
+.code i
+fails and the loop terminates.
+
+.coNP Functions @ rplaca and @ rplacd
+.synb
+.mets (rplaca < cons << new-car-value )
+.mets (rplacd < cons << new-cdr-value )
+.syne
+.desc
+The
+.code rplaca
+and
+.code rplacd
+functions assign new values into the
+.code car
+and
+.code cdr
+fields of the cell
+.metn cons .
+Note that
+.code (rplaca x y)
+is the same as the more generic
+.codn (set (car x) y) ,
+and likewise
+.code (rplacd x y)
+can be written as
+.codn (set (cdr x) y) .
+
+It is an error if
+.meta cons
+is not a cons or lazy cons. In particular,
+whereas
+.code (car nil)
+is correct,
+.code (rplaca nil ...)
+is erroneous.
+
+The
+.code rplaca
+and
+.code rplacd
+functions return
+.metn cons .
Note: TXR versions 89 and earlier, these functions returned the new value.
The behavior was undocumented.
-.SS Functions second, third, fourth, fifth and sixth
-
-.TP
-Syntax:
-
- (first <list>)
- (second <list>)
- (third <list>)
- (fourth <list>)
- (fifth <list>)
- (sixth <list>)
-
-.TP
-Description:
-
+.coNP Functions @, second @, third @, fourth @ fifth and @ sixth
+.synb
+.mets (first << list )
+.mets (second << list )
+.mets (third << list )
+.mets (fourth << list )
+.mets (fifth << list )
+.mets (sixth << list )
+.syne
+.desc
These functions access the elements of a proper list by position.
-If the list is shorter than implied, these functions return nil.
-
-.TP
-Examples:
+If the list is shorter than implied, these functions return
+.codn nil .
+.TP* Examples:
+.cblk
(third '(1 2)) -> nil
(second '(1 2)) -> 2
(third '(1 2 . 3)) -> **error**
-
-.SS Functions append, nconc and append*
-
-.TP
-Syntax:
-
- (append [<list>* <last-arg>])
- (nconc [<list>* <last-arg>])
- (append* [<list>* <last-arg>])
-
-.TP
-Description:
-
-The append function creates a new list which is a catenation of the
-<list> arguments. All arguments are optional, such that (append) produces
-the empty list.
-
-If a single argument is specified, then append simply returns the value of that
+.cble
+
+.coNP Functions @, append @ nconc and @ append*
+.synb
+.mets (append <> [ list * << last-arg ])
+.mets (nconc <> [ list * << last-arg ])
+.mets (append* <> [ list * << last-arg ])
+.desc
+The
+.code append
+function creates a new list which is a catenation of the
+.meta list
+arguments. All arguments are optional;
+.code (append)
+produces the empty list.
+
+If a single argument is specified, then
+.code append
+simply returns the value of that
argument. It may be any kind of object.
If N arguments are specified, where N > 1, then the first N-1 arguments must be
proper lists. Copies of these lists are catenated together. The last argument
-N, shown in the above syntax as <last-arg>, may be any kind of object. It is
-installed into the cdr field of the last cons cell of the resulting list.
+N, shown in the above syntax as
+.metn last-arg ,
+may be any kind of object. It is
+installed into the
+.code cdr
+field of the last cons cell of the resulting list.
Thus, if argument N is also a list, it is catenated onto the resulting list,
-but without being copied. Argument N may be an atom other than nil; in that
-case append produces an improper list.
-
-The nconc function works like append, but avoids consing. It destructively
+but without being copied. Argument N may be an atom other than
+.codn nil ;
+in that case
+.code append
+produces an improper list.
+
+The
+.code nconc
+function works like
+.codn append ,
+but avoids consing. It destructively
manipulates (that is to say, mutates) incoming lists to catenate them, and so
must be used with care.
-The append* function works like append, but returns a lazy list which produces
+The
+.code append*
+function works like
+.codn append ,
+but returns a lazy list which produces
the catenation of the lists on demand. If some of the arguments are
-themselves lazy lists which are infinite, then append* can return immediately,
+themselves lazy lists which are infinite, then
+.code append*
+can return immediately,
whereas append will get caught in an infinite loop trying to produce a
catenation and eventually exhaust available memory. (However, the last
argument to append may be an infinite lazy list, because append does not
traverse the last argument.)
-.TP
-Examples:
-
+.TP* Examples:
+.cblk
;; An atom is returned.
(append 3) -> 3
;; A list is also just returned: no copying takes place.
;; The eq function can verify that the same object emerges
;; from append that went in.
- (let ((list '(1 2 3)))
+ (let ((list '(1 2 3)))
(eq (append list) list)) -> t
(append '(1 2 3) '(4 5 6) 7) -> '(1 2 3 4 5 6 . 7))
@@ -7435,225 +12124,314 @@ Examples:
;; atoms and improper lists other than in the last position
;; are erroneous
(append '(a . b) 3 '(1 2 3)) -> **error**
-
-.SS Function list
-
-.TP
-Syntax:
-
-(list <value>*)
-
-.TP
-Description:
-
-The list function creates a new list, whose elements are the
+.cble
+
+.coNP Function @ list
+.synb
+.mets (list << value *)
+.syne
+.desc
+The
+.code list
+function creates a new list, whose elements are the
argument values.
-.TP
-Examples:
-
+.TP* Examples:
+.cblk
(list) -> nil
(list 1) -> (1)
(list 'a 'b) -> (a b)
-
-.SS Function list*
-
-.TP
-Syntax:
-
-(list* <value>*)
-
-.TP
-Description:
-
-The list* function is a generalization of cons. If called with exactly
-two arguments, it behaves exactly like cons: (list* x y) is
-identical to (cons x y). If three or more arguments are specified,
+.cble
+
+.coNP Function @ list*
+.synb
+.mets >> ( list* << value *)
+.syne
+.desc
+The
+.code list*
+function is a generalization of cons. If called with exactly
+two arguments, it behaves exactly like cons:
+.code (list* x y)
+is identical to
+.codn (cons x y) .
+If three or more arguments are specified,
the leading arguments specify additional atoms to be consed to the
-front of the list. So for instance (list* 1 2 3) is the same as
-(cons 1 (cons 2 3)) and produces the improper list (1 2 . 3).
-Generalizing in the other direction, list* can be called with just
+front of the list. So for instance
+.code (list* 1 2 3)
+is the same as
+.code (cons 1 (cons 2 3))
+and produces the improper list
+.codn (1 2 . 3) .
+Generalizing in the other direction,
+.code list*
+can be called with just
one argument, in which case it returns that argument, and
-can also be called with no arguments in which case it returns nil.
-
-.TP
-Examples:
+can also be called with no arguments in which case it returns
+.codn nil .
+.TP* Examples:
+.cblk
(list*) -> nil
(list* 1) -> 1
(list* 'a 'b) -> (a . b)
(list* 'a 'b 'c) -> (a b . c)
+.cble
-.TP
-Dialect Note:
-
+.TP* "Dialect Note:"
Note that unlike in some other Lisp dialects, the effect
-of (list* 1 2 x) can also be obtained using (list 1 2 . x).
-However, (list* 1 2 (func 3)) cannot be rewritten as (list 1 2 . (func 3))
-because the latter is equivalent to (list 1 2 func 3).
-
-.SS Function sub-list
-
-.TP
-Syntax:
-
- (sub-list <list> [<from> [<to>]])
-
-.TP
-Description:
-
-This function is like the sub function, except that it operates
+of
+.code (list* 1 2 x)
+can also be obtained using
+.codn (list 1 2 . x) .
+However,
+.code (list* 1 2 (func 3))
+cannot be rewritten as
+.code (list 1 2 . (func 3))
+because the latter is equivalent to
+.codn (list 1 2 func 3) .
+
+.coNP Function @ sub-list
+.synb
+.mets (sub-list < list >> [ from <> [ to ]])
+.syne
+.desc
+This function is like the
+.code sub
+function, except that it operates
strictly on lists.
-For a description of the arguments and semantics, refer to the sub function.
-
-.SS Function replace-list
-
-.TP
-Syntax:
-
- (replace-list <list> <item-sequence> [<from> [<to>]])
-
-.TP
-Description:
+For a description of the arguments and semantics, refer to the
+.code sub
+function.
-The replace-list function is like the replace function, except that the first
+.coNP Function @ replace-list
+.synb
+.mets (replace-list < list < item-sequence >> [ from <> [ to ]])
+.syne
+.desc
+The
+.code replace-list
+function is like the replace function, except that the first
argument must be a list.
-For a description of the arguments and semantics, refer to the replace function.
-
-.SS Functions listp and proper-listp
-
-.TP
-Syntax:
-
- (listp <value>)
- (proper-listp <value>)
-
-.TP
-Description:
-
-The listp and proper-listp functions test, respectively, whether
-<value> is a list, or a proper list, and return
-t or nil accordingly.
-
-The listp test is weaker, and executes without having to traverse
-the object. (listp x) is equivalent to (or (null x) (consp x)).
-The empty list is a list, and a cons cell is a list.
+For a description of the arguments and semantics, refer to the
+.code replace
+function.
-The proper-listp function returns t only for proper lists. A proper list is
-either nil, or a cons whose cdr is a proper list. proper-listp traverses the
+.coNP Functions @ listp and @ proper-listp
+.synb
+.mets (listp << value )
+.mets (proper-listp << value )
+.syne
+.desc
+The
+.code listp
+and
+.code proper-listp
+functions test, respectively, whether
+.meta value
+is a list, or a proper list, and return
+.code t
+or
+.code nil
+accordingly.
+
+The
+.code listp
+test is weaker, and executes without having to traverse
+the object.
+.code (listp x)
+is equivalent to
+.codn (or (null x) (consp x)) .
+The empty list
+.code nil
+is a list, and a cons cell is a list.
+
+The
+.code proper-listp
+function returns
+.code t
+only for proper lists. A proper list is
+either
+.codn nil ,
+or a cons whose
+.code cdr
+is a proper list.
+.code proper-listp
+traverses the
list, and its execution will not terminate if the list is circular.
-.SS Function length-list
-
-.TP
-Syntax:
-
-(length-list <list>)
-
-.TP
-Description:
-
-The length-list function returns the length of <list>, which may be
+.coNP Function @ length-list
+.synb
+.mets (length-list << list )
+.syne
+.desc
+The
+.code length-list
+function returns the length of
+.metn list ,
+which may be
a proper or improper list. The length of a list is the number of conses in that
list.
-.SS Function copy-list
-
-.TP
-Syntax:
-
- (copy-list <list>)
-
-.TP
-Description:
-
-The copy-list function which returns a list similar to <list>, but with
+.coNP Function @ copy-list
+.synb
+.mets (copy-list << list )
+.syne
+.desc
+The
+.code copy-list
+function which returns a list similar to
+.metn list ,
+but with
a newly allocated cons cell structure.
-If <list> is an atom, it is simply returned.
-
-Otherwise, <list> is a cons cell, and copy-list returns
-(cons (car <list>) (copy-list (cdr <list>))) except that recursion
-is not necessarily used.
-
-Note that the object (car <list>) is not deeply copied, but only
-propagated by reference into the new list. copy-list produces
-a new list structure out of the same items that are in <list>.
-
-.TP
-Dialect Note:
-
+If
+.meta list
+is an atom, it is simply returned.
+
+Otherwise,
+.meta list
+is a cons cell, and
+.code copy-list
+returns the same object as the expression
+.cblk
+.meti (cons (car << list ) (copy-list (cdr << list ))).
+.cble
+
+Note that the object
+.cblk
+.meti (car << list )
+.cble
+is not deeply copied, but only
+propagated by reference into the new list.
+.code copy-list
+produces
+a new list structure out of the same items that are in
+.metn list .
+
+.TP* "Dialect Note:"
Common Lisp does not allow the argument to be an atom, except
-for the empty list nil.
-
-.SS Function copy-cons
-
-.TP
-Syntax:
-
- (copy-cons <cons>)
-
-.TP
-Description:
-
-This function creates a fresh cons cell, whose car and cdr fields are
-copied from <cons>.
-
-.SS Functions reverse, nreverse
-
-.TP
-Syntax:
-
- (reverse <list>)
- (nreverse <list>)
-
-.TP
-Description:
-
-The functions reverse and nreverse produce an object which contains
-the same items as proper list <list>, but in reverse order.
-If <list> is nil, then both functions return nil.
-
-The reverse function is non-destructive: it creates a new list.
-
-The nreverse function creates the structure of the reversed list out of the
+for the empty list
+.codn nil .
+
+.coNP Function @ copy-cons
+.synb
+.mets (copy-cons << cons )
+.syne
+.desc
+This function creates a fresh cons cell, whose
+.code car
+and
+.code cdr
+fields are copied from
+.codn cons .
+
+.coNP Functions @ reverse and @ nreverse
+.synb
+.mets (reverse << list )
+.mets (nreverse << list )
+.syne
+.desc
+Description:
+
+The functions
+.code reverse
+and
+.code nreverse
+produce an object which contains
+the same items as proper list
+.metn list ,
+but in reverse order.
+If
+.meta list
+is
+.codn nil ,
+then both functions return
+.codn nil .
+
+The
+.code reverse
+function is non-destructive: it creates a new list.
+
+The
+.code nreverse
+function creates the structure of the reversed list out of the
cons cells of the input list, thereby destructively altering it (if it contains
-more than one element). How nreverse uses the material from the original list
+more than one element). How
+.code nreverse
+uses the material from the original list
is unspecified. It may rearrange the cons cells into a reverse order, or it may
-keep the structure intact, but transfer the "car" values among cons cells into
+keep the structure intact, but transfer the
+.code car
+values among cons cells into
reverse order. Other approaches are possible.
-.SS Function ldiff
-
-.TP
-Syntax:
-
- (ldiff <list> <sublist>)
-
-.TP
-Description:
-
-The values <list> and <sublist> are proper lists.
-
-The ldiff function determines whether <sublist> is a structural suffix of
-<list> (meaning that it actually is a suffix, and is not merely equal to one).
-
-This is true if <list> and <sublist> are the same object, or else,
-recursively, if <sublist> is a suffix of (cdr <list>).
-
-The object nil is the sublist of every list, including itself.
+.coNP Function @ ldiff
+.synb
+.mets (ldiff < list << sublist )
+.syne
+.desc
+The values
+.meta list
+and
+.meta sublist
+are proper lists.
+
+The
+.code ldiff
+function determines whether
+.meta sublist
+is a structural suffix of
+.meta list
+(meaning that it actually is a suffix, and is not merely equal to one).
+
+This is true if
+.meta list
+and
+.meta sublist
+are the same object, or else,
+recursively, if
+.meta sublist
+is a suffix of
+.cblk
+.meti (cdr << list ).
+.cble
+
+The object
+.code nil
+is the sublist of every list, including itself.
The ldiff function returns a new list consisting of the elements of
-the prefix of <list> which come before the <sublist> suffix. The elements
-are in the same order as in <list>. If <sublist> is not a suffix of <list>,
-then a copy of <list> is returned.
-
-.TP
-Examples:
+the prefix of
+.meta list
+which come before the
+.meta sublist
+suffix. The elements
+are in the same order as in
+.metn list .
+If
+.meta sublist
+is not a suffix of
+.metn list ,
+then a copy of
+.meta list
+is returned.
- ;;; unspecified: the compiler could make '(2 3) a suffix of '(1 2 3),
+These functions also work more generally on sequences.
+The
+.meta list
+and
+.meta sublist
+arguments may be strings or vectors. In this case, the suffixing
+matching behavior is relaxed to one of structural equivalence.
+See the relevant examples below.
+
+.TP* Examples:
+.cblk
+ ;;; unspecified: the compiler could make
+ ;;; '(2 3) a suffix of '(1 2 3),
;;; or they could be separate objects.
(ldiff '(1 2 3) '(2 3)) -> either (1) or (1 2 3)
@@ -7662,204 +12440,327 @@ Examples:
(ldiff a b))
-> (1)
-.SS Function last
-
-.TP
-Syntax:
-
- (last <list>)
+ ;; string and vector behavior
+ (ldiff "abc" "bc") -> "a"
-.TP
-Description:
+ (ldiff "abc" nil) -> "abc"
-If <list> is a nonempty proper or improper list, the last function
-returns the last cons cell in the list: that cons cell whose cdr field
-is a terminating atom.
+ (ldiff #(1 2 3) #(3)) -> #(1 2)
-If <list> is nil, then nil is returned.
+ ;; mixtures do not have above behavior
+ (ldiff #(1 2 3) '(3)) -> #(1 2 3)
-.SS Functions flatten, flatten*
+ (ldiff '(1 2 3) #(3)) -> #(1 2 3)
-.TP
-Syntax:
+ (ldiff "abc" #(#\eb #\ec)) -> "abc"
+.cble
- (flatten <list>)
- (flatten* <list>)
+.coNP Function @ last
+.synb
+.mets (last << list )
+.syne
+.desc
+If
+.meta list
+is a nonempty proper or improper list, the
+.code last
+function
+returns the last cons cell in the list: that cons cell whose
+.code cdr
+field is a terminating atom.
-.TP
-Description:
+If
+.meta list
+is
+.codn nil ,
+then
+.code nil
+is returned.
-The flatten function produces a list whose elements are all of the non-nil
-atoms contained in the structure of <list>. The flatten* function
-works like flatten except that flatten creates and returns a complete
-flattened list, whereas flatten* produces a lazy list which is
+.coNP Functions @ flatten and @ flatten*
+.synb
+.mets (flatten << list )
+.mets (flatten* << list )
+.syne
+.desc
+The
+.code flatten
+function produces a list whose elements are all of the
+.cod2 non- nil
+atoms contained in the structure of
+.metn list .
+The
+.code flatten*
+function
+works like
+.code flatten
+except that
+.code flatten
+creates and returns a complete
+flattened list, whereas
+.code flatten*
+produces a lazy list which is
instantiated on demand. This is particularly useful when the input
structure is itself lazy.
-.TP
-Examples:
-
+.TP* Examples:
+.cblk
(flatten '(1 2 () (3 4))) -> (1 2 3 4)
- ;; precisely equivalent to previous example! nil is the same thing as ()
+ ;; equivalent to previous, since
+ ;; nil is the same thing as ()
(flatten '(1 2 nil (3 4))) -> (1 2 3 4)
(flatten nil) -> nil
(flatten '(((()) ()))) -> nil
+.cble
+
+.coNP Functions @, memq @ memql and @ memqual
+.synb
+.mets (memq < object << list )
+.mets (memql < object << list )
+.mets (memqual < object << list )
+.syne
+.desc
+
+The
+.codn memq ,
+.code memql
+and
+.code memqual
+functions search
+.meta list
+for a member
+which is, respectively,
+.codn eq ,
+.code eql
+or
+.coe equal
+to
+.metn object .
+(See the
+.codn eq ,
+.code eql
+and
+.code equal
+functions above.)
+
+If no such element found,
+.code nil
+is returned.
-.SS Functions memq, memql and memqual
-
-.TP
-Syntax:
-
- (memq <object> <list>)
- (memql <object> <list>)
- (memqual <object> <list>)
-
-.TP
-Description:
-
-The memq, memql and memqual functions search the <list> for a member
-which is, respectively, eq, eql or equal to <object>. (See the eq, eql and
-equal functions below.)
-
-If no such element found, nil is returned.
-
-Otherwise, that tail of the list is returned whose first element
+Otherwise, that suffix of
+.meta list
+is returned whose first element
is the matching object.
-.SS Functions member and member-if
-
-.TP
-Syntax:
-
- (member <key> <sequence> [<testfun> [<keyfun>]])
- (member-if <predfun> <sequence> [<keyfun>])
-
-.TP
-Description:
-
-The find and find-if functions search through <sequence> for an item which
+.coNP Functions @ member and @ member-if
+.synb
+.mets (member < key < sequence >> [ testfun <> [ keyfun ]])
+.mets (member-if < predfun < sequence <> [ keyfun ])
+.syne
+.desc
+
+The
+.code member
+and
+.code member-if
+functions search through
+.meta sequence
+for an item which
matches a key, or satisfies a predicate function, respectively.
-The keyfun argument specifies a function which is applied to the elements
+The
+.meta keyfun
+argument specifies a function which is applied to the elements
of the sequence to produce the comparison key. If this argument is omitted,
then the untransformed elements of the sequence themselves are examined.
-The member function's testfun argument specifies the test function which is
+The
+.code member
+function's
+.meta testfun
+argument specifies the test function which is
used to compare the comparison keys taken from the sequence to the search key.
-If this argument is omitted, then the equal function is used.
-If member does not find a matching element, it returns nil. Otherwise it
-returns the suffix of <sequence> which begins with the matching element.
-
-The member-if function's predfun argument specifies a predicate function
+If this argument is omitted, then the
+.code equal
+function is used.
+If
+.code member
+does not find a matching element, it returns
+.codn nil .
+Otherwise it
+returns the suffix of
+.meta sequence
+which begins with the matching element.
+
+The
+.code member-if
+function's
+.meta predfun
+argument specifies a predicate function
which is applied to the successive comparison keys pulled from the sequence
by applying the key function to successive elements. If no match is found,
-then nil is returned, otherwise the suffix of <sequence> which begins
-with the matching element.
-
-.SS Functions remq, remql and remqual
-
-.TP
-Syntax:
-
- (remq <object> <list>)
- (remql <object> <list>)
- (remqual <object> <list>)
-
-.TP
-Description
-
-The remq, remql and remqual functions produce a new list based on <list>,
-removing the items which are eq, eql or equal to <object>.
-
-The input <list> is unmodified, but the returned list may share substructure
+then
+.code nil
+is returned, otherwise what is returned is the suffix of
+.meta sequence
+which begins with the matching element.
+
+.coNP Functions @, remq @ remql and @ remqual
+.synb
+.mets (remq < object << list )
+.mets (remql < object << list )
+.mets (remqual < object << list )
+.syne
+.desc
+The
+.codn remq ,
+.code remql
+and
+.code remqual
+functions produce a new list based on
+.metn list ,
+removing the items which are
+.codn eq ,
+.code eql
+or
+.code equal
+to
+.metn object .
+
+The input
+.meta list
+is unmodified, but the returned list may share substructure
with it. If no items are removed, it is possible that the return value
-is <list> itself.
-
-.SS Functions remq*, remql* and remqual*
-
-.TP
-Syntax:
-
- (remq* <object> <list>)
- (remql* <object> <list>)
- (remqual* <object> <list>)
-
-.TP
-Description:
-
-The remq*, remql* and remqual* functions are lazy versions of
-remq, remql and remqual. Rather than computing the entire new list
+is
+.meta list
+itself.
+
+.coNP Functions @, remq @ remql* and @ remqual*
+.synb
+.mets (remq* < object << list )
+.mets (remql* < object << list )
+.mets (remqual* < object << list )
+.syne
+.desc
+The
+.codn remq* ,
+.code remql*
+and
+.code remqual*
+functions are lazy versions of
+.codn remq ,
+.code remql
+and
+.codn remqual .
+Rather than computing the entire new list
prior to returning, these functions return a lazy list.
Caution: these functions can still get into infinite looping behavior.
-For instance, in (remql* 0 (repeat '(0))), remql will keep consuming
-the 0 values coming out of the infinite list, looking for the first item that
+For instance, in
+.codn (remql* 0 (repeat '(0))) ,
+.code remql
+will keep consuming
+the
+.code 0
+values coming out of the infinite list, looking for the first item that
does not have to be deleted, in order to instantiate the first lazy value.
-.TP
-Examples:
-
+.TP* Examples:
+.cblk
;; Return a list of all the natural numbers, excluding 13,
;; then take the first 100 of these.
;; If remql is used, it will loop until memory is exhausted,
;; because (range 1) is an infinite list.
[(remql* 13 (range 1)) 0..100]
-
-.SS Functions countqual, countql and countq
-
-.TP
-Syntax:
-
- (countq <object> <list>)
- (countql <object> <list>)
- (countqual <object> <list>)
-
-.TP
-Description
-
-The countq, countql and countqual functions count the number of objects
-in <list> which are eq, eql or equal to <object>, and return the count.
-
-.SH APPLICATIVE LIST PROCESSING
-
-.SS Functions remove-if, keep-if, remove-if* and keep-if*
-
-.TP
-Syntax:
-
- (remove-if <predicate-function> <list> [<key-function>])
- (keep-if <predicate-function> <list> [<key-function>])
- (remove-if* <predicate-function> <list> [<key-function>])
- (keep-if* <predicate-function> <list> [<key-function>])
-
-.TP
-Description
-
-The remove-if function produces a list whose contents are those of
-<list> but with those elements removed which satisfy <predicate-function>.
+.cble
+
+.coNP Functions @, countqual @ countql and @ countq
+.synb
+.mets (countq < object << list )
+.mets (countql < object << list )
+.mets (countqual < object << list )
+.syne
+.desc
+The
+.codn countq ,
+.code countql
+and
+.code countqual
+functions count the number of objects
+in
+.meta list
+which are
+.codn eq ,
+.code eql
+or
+.code equal
+to
+.metn object ,
+and return the count.
+
+.SS* Applicative List Processing
+.coNP Functions @, remove-if @, keep-if @ remove-if* and @ keep-if*
+.synb
+.mets (remove-if < predicate-function < list <> [ key-function ])
+.mets (keep-if < predicate-function < list <> [ key-function ])
+.mets (remove-if* < predicate-function < list <> [ key-function ])
+.mets (keep-if* < predicate-function < list <> [ key-function ])
+.syne
+.desc
+
+The
+.code remove-if
+function produces a list whose contents are those of
+.meta list
+but with those elements removed which satisfy
+.metn predicate-function .
Those elements which are not removed appear in the same order.
The result list may share substructure with the input list,
and may even be the same list object if no items are removed.
-The optional <key-function> specifies how each element from the <list> is
-transformed to an argument to <predicate-function>. If this argument is omitted
+The optional
+.meta key-function
+specifies how each element from the
+.meta list
+is transformed to an argument to
+.metn predicate-function .
+If this argument is omitted
then the predicate function is applied to the elements directly, a behavior
-which is identical to <key-function> being (fun identity).
-
-The keep-if function is exactly like remove-if, except the sense of
-the predicate is inverted. The function keep-if retains those items
-which remove-if will delete, and removes those that remove-if will preserve.
-
-The remove-if* and keep-if* are like remove-if and keep-if, but
-produce lazy lists.
-
-.TP
-Examples:
-
+which is identical to
+.meta key-function
+being
+.codn (fun identity) .
+
+The
+.code keep-if
+function is exactly like
+.codn remove-if ,
+except the sense of
+the predicate is inverted. The function
+.code keep-if
+retains those items
+which
+.code remove-if
+will delete, and removes those that
+.code remove-if
+will preserve.
+
+The
+.code remove-if*
+and
+.code keep-if*
+functions are like
+.code remove-if
+and
+.codn keep-if ,
+but produce lazy lists.
+
+.TP* Examples:
+.cblk
;; remove any element numerically equal to 3.
(remove-if (op = 3) '(1 2 3 4 3.0 5)) -> (1 2 4 5)
@@ -7873,429 +12774,785 @@ Examples:
(remove-if (op equal [(car @1) 0..3] "abc")
'(("abcd" 4) ("defg" 5)))
-> (("defg 5))
-
-.SS Function count-if
-
-.TP
-Syntax:
-
- (count-if <predicate-function> <list> [<key-function>])
-
-.TP
-Description:
-
-The count-if function counts the number of elements of <list> which satisfy
-<predicate-function> and returns the count.
-
-The optional <key-function> specifies how each element from the <list> is
-transformed to an argument to <predicate-function>. If this argument is omitted
+.cble
+
+.coNP Function @ count-if
+.synb
+.mets (count-if < predicate-function < list <> [ key-function ])
+.syne
+.desc
+The
+.code count-if
+function counts the number of elements of
+.meta list
+which satisfy
+.meta predicate-function
+and returns the count.
+
+The optional
+.meta key-function
+specifies how each element from the
+.meta list
+is transformed to an argument to
+.metn predicate-function .
+If this argument is omitted
then the predicate function is applied to the elements directly, a behavior
-which is identical to <key-function> being (fun identity).
-
-.SS Functions posqual, posql and posq
-
-.TP
-Syntax:
-
- (posq <object> <list>)
- (posql <object> <list>)
- (posqual <object> <list>)
-
-.TP
-Description
-
-The posq, posql and posqual functions return the zero-based position of the
-first item in <list> which is, respectively, eq, eql or equal to <object>.
-
-.SS Functions posqual, posql and posq
-
-.TP
-Syntax:
-
- (posq <object> <list>)
- (posql <object> <list>)
- (posqual <object> <list>)
-
-.TP
-Description
-
-The posq, posql and posqual functions return the zero-based position of the
-first item in <list> which is, respectively, eq, eql or equal to <object>.
-
-.SS Functions pos and pos-if
-
-.TP
-Syntax:
-
- (pos <key> <list> [<testfun> [<keyfun>]])
- (pos-if <predfun> <list> [<keyfun>])
-
-.TP
-Description:
-
-The pos and pos-if functions search through a list for an item which
-matches a key, or satisfies a predicate function, respectively.
-They return the zero based position of the matching item.
-
-The keyfun argument specifies a function which is applied to the elements
-of the list to produce the comparison key. If this argument is omitted,
-then the untransformed elements of the list themselves are examined.
-
-The pos function's testfun argument specifies the test function which
-is used to compare the comparison keys from the list to the search key.
-If this argument is omitted, then the equal function is used.
-The position of the first element from the list whose comparison key (as
-retrieved by the key function) matches the search (under the test function) is
-returned. If no such element is found, nil is returned.
-
-The pos-if function's predfun argument specifies a predicate function
-which is applied to the successive comparison keys pulled from the list
-by applying the key function to successive elements. The position of
-the first element for which the predicate function yields true is returned. If
-no such element is found, nil is returned.
-
-.SS Functions pos-max and pos-min
-
-.TP
-Syntax:
-
- (pos-max <sequence> [<testfun> [<keyfun>]])
- (pos-min <sequence> [<testfun> [<keyfun>]])
-
-.TP
-Description:
+which is identical to
+.meta key-function
+being
+.codn (fun identity) .
+
+.coNP Functions @, posqual @ posql and @ posq
+.synb
+.mets (posq < object << list )
+.mets (posql < object << list )
+.mets (posqual < object << list )
+.syne
+.desc
+The
+.codn posq ,
+.code posql
+and
+.code posqual
+functions return the zero-based position of the
+first item in
+.meta list
+which is, respectively,
+.codn eq ,
+.code eql
+or
+.code equal
+to
+.metn object .
+
+.coNP Functions @, posqual @ posql and @ posq
+.synb
+.mets (posq < object << list )
+.mets (posql < object << list )
+.mets (posqual < object << list )
+.syne
+.desc
+The
+.codn posq ,
+.code posql
+and
+.code posqual
+functions return the zero-based position of the
+first item in
+.meta list
+which is, respectively,
+.codn eq ,
+.code eql
+or
+.code equal
+to
+.metn object .
+
+.coNP Functions @ pos and @ pos-if
+.synb
+.mets (pos < key < list >> [ testfun <> [ keyfun ]])
+.mets (pos-if < predfun < list <> [ keyfun ])
+.syne
+.desc
+
+The
+.code pos
+and
+.code pos-if
+functions search through
+.meta list
+for an item which matches
+.metn key ,
+or satisfies predicate function
+.metn predfun ,
+respectively.
+They return the zero-based position of the matching item.
+
+The
+.meta keyfun
+argument specifies a function which is applied to the elements
+of
+.meta list
+to produce the comparison key. If this argument is omitted,
+then the untransformed elements of
+.meta list
+are examined.
+
+The
+.code pos
+function's
+.meta testfun
+argument specifies the test function which
+is used to compare the comparison keys from
+.meta list
+to
+.metn key .
+If this argument is omitted, then the
+.code equal
+function is used.
+The position of the first element
+.meta list
+whose comparison key (as
+retrieved by
+.metn keyfun )
+matches the search (under
+.metn testfun )
+is
+returned. If no such element is found,
+.code nil
+is returned.
-The pos-min and pos-max function implement exactly the same algorithm; they
-differ only in their defaulting behavior with regard to the <testfun>
-argument. If <testfun> is not given, then the pos-max function defaults it to
-the > function, whereas pos-min defaults it to the < function.
+The
+.code pos-if
+function's
+.meta predfun
+argument specifies a predicate function
+which is applied to the successive comparison keys taken from
+.meta list
+by applying
+.meta keyfun
+to successive elements. The position of
+the first element for which
+.meta predfun
+yields true is returned. If
+no such element is found,
+.code nil
+is returned.
-If <sequence> is empty, both functions return nil.
+.coNP Functions @ pos-max and @ pos-min
+.synb
+.mets (pos-max > sequence >> [ testfun <> [keyfun]])
+.mets (pos-min > sequence >> [ testfun <> [keyfun]])
+.syne
+.desc
+
+The
+.code pos-min
+and
+.code pos-max
+functions implement exactly the same algorithm; they
+differ only in their defaulting behavior with regard to the
+.meta testfun
+argument. If
+.meta testfun
+is not given, then the pos-max function defaults
+.meta testfun
+to the
+.code >
+("greater than") function, whereas
+.code pos-min
+defaults it to the
+.code <
+("less than")
+function.
-Without a <testfun> argument, the pos-max function finds the zero-based
-position index of the numerically maximum value occurring in <sequence>,
-whereas pos-min without a <testfun> argument finds the index of the minimum
+If
+.meta sequence
+is empty, both functions return
+.codn nil .
+
+Without a
+.meta testfun
+argument, the
+.code pos-max
+function finds the zero-based
+position index of the numerically maximum value occurring in
+.metn sequence ,
+whereas
+.code pos-min
+without a
+.meta testfun
+argument finds the index of the minimum
value.
-If a <testfun> argument is given, the two functions are equivalent.
-The <testfun> function must be callable with two arguments.
-If <testfun> behaves like a greater-than comparison, then pos-max
-and pos-min return the index of the maximum element. If <testfun>
-behaves like a less-than comparison, then the functions return
+If a
+.meta testfun
+argument is given, the two functions are equivalent.
+The
+.meta testfun
+function must be callable with two arguments.
+If
+.meta testfun
+behaves like a greater-than comparison, then
+.code pos-max
+and
+.code pos-min
+return the index of the maximum element. If
+.meta testfun
+behaves like a
+.code less-than
+comparison, then the functions return
the index of the minimum element.
-The <keyfun> argument defaults to the identity function. Each element
-from sequence is passed through this one-argument function, and
+The
+.meta keyfun
+argument defaults to the
+.code identity
+function. Each element
+from
+.meta sequence
+is passed through this one-argument function, and
the resulting value is used in its place.
-.SS Function where
-
-.TP
-Syntax:
-
- (where <object> <function>)
-
-.TP
-Description:
+.coNP Function @ where
+.synb
+.mets (where < object << function )
+.syne
+.desc
-If <object> is a sequence, the where function returns
+If
+.meta object
+is a sequence, the
+.code where
+function returns
a list of the numeric indices of those of its elements which satisfy
-<function>. The numeric indices appear in increasing order.
+.metn function .
+The numeric indices appear in increasing order.
-If <object> is a hash, the where function returns an unordered list
-of keys which have values which satisfy <function>.
-
-<function> must be a function that can be called with one argument.
-For each element of <object>, <function> is called with that element
-as an argument. If a non-nil value is returned, then the zero-based index of
+If
+.meta object
+is a hash, the
+.code where
+function returns an unordered list
+of keys which have values which satisfy
+.metn function .
+
+.meta function
+must be a function that can be called with one argument.
+For each element of
+.metn object ,
+.meta function
+is called with that element
+as an argument. If a
+.cod2 non- nil
+value is returned, then the zero-based index of
that element is added to a list. Finally, the list is returned.
-.SS Function select
+.coNP Function @ select
+.synb
+.mets (select < object << index-list )
+.syne
+.desc
+
+The
+.code select
+function returns an object, of the same kind as
+.metn object ,
+which consists of those elements of
+.meta object
+which are identified by
+the indices in
+.metn index-list .
-.TP
-Syntax:
-
- (select <object> <index-list>)
-
-.TP
-Description:
-
-The select function returns an object, of the same kind as <object>,
-which consists of those elements of <object> which are identified by
-the indices in <index-list>.
-
-If <object> is a sequence, then <index-list> consists of numeric
-indices. The select function stops processing <object> upon encountering an
-index inside <index-list> which is out of range. (Rationale: without
-this strict behavior, select would not be able to terminate if
-<index-list> is infinite.)
+If
+.meta object
+is a sequence, then
+.meta index-list
+consists of numeric
+indices. The
+.code select
+function stops processing
+.meta object
+upon encountering an
+index inside
+.meta index-list
+which is out of range. (Rationale: without
+this strict behavior,
+.code select
+would not be able to terminate if
+.meta index-list
+is infinite.)
-If <object> is a list, then <index-list> must contain monotonically increasing
-numeric values, even if no value is out of range, since the select function
+If
+.meta object
+is a list, then
+.meta index-list
+must contain monotonically increasing
+numeric values, even if no value is out of range, since the
+.code select
+function
makes a single pass through the list based on the assumption that indices
are ordered. (Rationale: optimization.)
-If <object> is a hash, then <index-list> is a list of keys. A new hash is
-returned which contains those elements of <object> whose keys appear
-in <index-list>. All of <index-list> is processed, even if it contains
-keys which are not in <object>.
-
-.SS Funtion partition
-
-.TP
-Syntax:
-
- (partition <sequence> {<index-list> | <index> | <function>})
-
-.TP
-Description:
-
-If <sequence> is empty, then partition returns an empty list, and the
-second argument is ignored; if it is <function>, it is not called.
-
-Otherwise, partition-by returns a lazy list of partitions of the sequence
-<sequence>. Partitions are consecutive, non-empty sub-strings of <sequence>,
-of the same kind as <sequence>.
+If
+.meta object
+is a hash, then
+.meta index-list
+is a list of keys. A new hash is
+returned which contains those elements of
+.meta object
+whose keys appear
+in
+.metn index-list .
+All of
+.meta index-list
+is processed, even if it contains
+keys which are not in
+.metn object .
+
+.coNP Funtion @ partition
+.synb
+.mets (partition < sequence >> { index-list >> | index <> | function })
+.syne
+.desc
-If the second argument is of the form <index-list>, it is a sequence of
+If
+.meta sequence
+is empty, then
+.code partition
+returns an empty list, and the
+second argument is ignored; if it is
+.metn function ,
+it is not called.
+
+Otherwise,
+.code partition
+returns a lazy list of partitions of the sequence
+
+.metn sequence .
+Partitions are consecutive, non-empty sub-strings of
+.metn sequence ,
+of the same kind as
+.metn sequence .
+
+
+If the second argument is of the form
+.metn index-list ,
+it is a sequence of
strictly increasing, positive integers. First, any leading zeros in this sequence
-are dropped. The partition function then divides <sequence> according to the
+are dropped. The
+.code partition
+function then divides
+.meta sequence
+according to the
indices in index list. The first partition begins with the first element of
-<sequence>. The second partition begins at the first position in <index-list>,
+.metn sequence .
+The second partition begins at the first position in
+.metn index-list ,
and so on. Indices beyond the length of the sequence are ignored.
-If <index-list> is empty then a one-element list containing the entire
-<sequence> is returned.
+If
+.meta index-list
+is empty then a one-element list containing the entire
+.meta sequence
+is returned.
If the second argument is a function, then this function is applied
-to <sequence>, and the return value of this call is then used in place of the
-second argument, which must be an <index> or <index-list>.
+to
+.metn sequence ,
+and the return value of this call is then used in place of the
+second argument, which must be an
+.meta index
+or
+.metn index-list .
If the second argument is an atom other than a function, it is assumed to be
-an integer index, and is turned into an <index-list> of one element.
-
-.TP
-Examples:
+an integer index, and is turned into an
+.meta index-list
+of one element.
+.TP* Examples:
+.cblk
(partition '(1 2 3) 1) -> ((1) (2 3))
;; split the string where there is a "b"
(partition "abcbcbd" (op where @1 (op eql #\eb))) -> ("a" "bc" "bc" "bd")
+.cble
-.SS Funtion partition*
-
-.TP
-Syntax:
-
- (partition* <sequence> {<index-list> | <index> | <function>})
+.coNP Function @ partition*
+.synb
+.mets (partition* < sequence >> { index-list >> | index <> | function })
+.syne
+.desc
-.TP
-Description:
-
-If <sequence> is empty, then partition returns an empty list, and the
-second argument is ignored; if it is <function>, it is not called.
-
-If the second argument is of the form <index-list>, which is a sequence
-of strictly increasing non-negative integers, then partition* produces
-lazy list of pieces taken from <sequence>. The pieces are formed by
-deleting from <sequence> the elements at the positions given
-in <index-list>. The pieces are the non-empty sub-strings between
+If
+.meta sequence
+is empty, then
+.code partition* returns an empty list, and the
+second argument is ignored; if it is
+.metn function ,
+it is not called.
+
+If the second argument is of the form
+.metn index-list ,
+which is a sequence
+of strictly increasing non-negative integers, then
+.code partition*
+produces
+lazy list of pieces taken from
+.metn sequence .
+The pieces are formed by
+deleting from
+.meta sequence
+the elements at the positions given
+in
+.metn index-list .
+The pieces are the non-empty sub-strings between
the deleted elements.
-If <index-list> is empty then a one-element list containing the entire
-<sequence> is returned.
+If
+.meta index-list
+is empty then a one-element list containing the entire
+
+.meta sequence
+is returned.
If the second argument is a function, then this function is applied
-to <sequence>, and the return value of this call is then used in place of the
-second argument, which must be an <index> or <index-list>.
+to
+.metn sequence ,
+and the return value of this call is then used in place of the
+second argument, which must be an
+.meta index
+or
+.metn index-list .
If the second argument is an atom other than a function, it is assumed to be
-an integer index, and is turned into an <index-list> of one element.
-
-
-.TP
-Examples:
+an integer index, and is turned into an
+.meta index-list
+of one element.
+.TP* Examples:
+.cblk
(partition* '(1 2 3 4 5) '(0 2 4)) -> ((1) (3) (5))
(partition* "abcd" '(0 3)) -> "bc"
(partition* "abcd" '(0 1 2 3)) -> nil
-
-
-.SS Function tree-find
-
-.TP
-Syntax:
-
- (tree-find <obj> <tree> <test-function>)
-
-.TP
-Description:
-
-The tree-find function searches <tree> for an occurrence of <obj>. Tree can be
-any atom, or a cons. If <tree> it is a cons, it is understood to be a proper
+.cble
+
+.coNP Function @ tree-find
+.synb
+.mets (tree-find < obj < tree << test-function )
+.syne
+.desc
+
+The
+.code tree-find
+function searches
+.meta tree
+for an occurrence of
+.metn obj .
+Tree can be
+any atom, or a cons. If
+.meta tree
+it is a cons, it is understood to be a proper
list whose elements are also trees.
-The equivalence test is performed by <test-function> which must take two
-arguments, and has conventions similar to eq, eql or equal.
-
-tree-find works as follows. If <tree> is equivalent to <obj> under
-<test-function>, then t is returned to announce a successful finding.
-If this test fails, and <tree> is an atom, nil is returned immediately to
-indicate that the find failed. Otherwise, <tree> is taken to be a proper list,
+The equivalence test is performed by
+.meta test-function
+which must take two
+arguments, and has conventions similar to
+.codn eq ,
+.code eql
+or
+.codn equal .
+
+.code tree-find
+works as follows. If
+.meta tree
+is equivalent to
+.meta obj
+under
+.metn test-function ,
+then
+.code t
+is returned to announce a successful finding.
+If this test fails, and
+.meta tree
+is an atom,
+.code nil
+is returned immediately to
+indicate that the find failed. Otherwise,
+.meta tree
+is taken to be a proper list,
and tree-find is recursively applied to each element of the list in turn, using
-the same <obj> and <test-function> arguments, stopping at the first element
-which returns non-nil.
-
-.SS Functions find and find-if
-
-.TP
-Syntax:
-
- (find <key> <list> [<testfun> [<keyfun>]])
- (find-if <predfun> <list> [<keyfun>])
-
-.TP
-Description:
+the same
+.meta obj
+and
+.meta test-function
+arguments, stopping at the first element
+which returns a
+.cod2 non- nil
+value.
-The find and find-if functions search through a list for an item which
+.coNP Functions @ find and @ find-if
+.synb
+.mets (find < key < sequence >> [ testfun <> [ keyfun ]])
+.mets (find-if < predfun < sequence <> [ keyfun ])
+.syne
+.desc
+The
+.code find
+and
+.code find-if
+functions search through a sequence for an item which
matches a key, or satisfies a predicate function, respectively.
-The keyfun argument specifies a function which is applied to the elements
-of the list to produce the comparison key. If this argument is omitted,
-then the untransformed elements of the list themselves are searched.
-
-The find function's testfun argument specifies the test function which
-is used to compare the comparison keys from the list to the search key.
-If this argument is omitted, then the equal function is used.
+The
+.meta keyfun
+argument specifies a function which is applied to the elements
+of
+.meta sequence
+to produce the comparison key. If this argument is omitted,
+then the untransformed elements of the
+.meta sequence
+are searched.
+
+The
+.code find
+function's
+.meta testfun
+argument specifies the test function which
+is used to compare the comparison keys from
+.meta sequence
+to the search key.
+If this argument is omitted, then the
+.code equal
+function is used.
The first element from the list whose comparison key (as retrieved by
-the key function) matches the search (under the test function)
-is returned. If no such element is found, nil is returned.
+.metn keyfun )
+matches the search (under
+.metn testfun )
+is returned. If no such element is found,
+.code nil
+is returned.
-The find-if function's predfun argument specifies a predicate function
+The
+.code find-if
+function's
+.meta predfun
+argument specifies a predicate function
which is applied to the successive comparison keys pulled from the list
-by applying the key function to successive elements. The first element
-for which the predicate function yields true is returned. If no such
-element is found, nil is returned.
-
-.SS Functions find-max and find-min
-
-.TP
-Syntax:
-
- (find-max <sequence> [<testfun> [<keyfun>]])
- (find-min <sequence> [<testfun> [<keyfun>]])
-
-.TP
-Description:
+by applying
+.meta keyfun
+to successive elements. The first element
+for which
+.meta predfun
+yields true is returned. If no such
+element is found,
+.code nil
+is returned.
-The find-min and find-max function implement exactly the same algorithm; they
-differ only in their defaulting behavior with regard to the <testfun>
-argument. If <testfun> is not given, then the find-max function defaults it to
-the > function, whereas find-min defaults it to the < function.
+.coNP Functions @ find-max and @ find-min
+.synb
+.mets (find-max < sequence >> [ testfun <> [ keyfun ]])
+.mets (find-min < sequence >> [ testfun <> [ keyfun ]])
+.syne
+.desc
+The
+.code find-min
+and
+.code find-max
+function implement exactly the same algorithm; they
+differ only in their defaulting behavior with regard to the
+.meta testfun
+argument. If
+.meta testfun
+is not given, then the find-max function defaults it to
+the
+.code >
+function, whereas
+.code find-min
+defaults it to the
+.code <
+function.
-Without a <testfun> argument, the find-max function finds the numerically
-maximum value occurring in <sequence>, whereas pos-min without a <testfun>
+Without a
+.meta testfun
+argument, the
+.code find-max
+function finds the numerically
+maximum value occurring in
+.metn sequence ,
+whereas
+.code pos-min
+without a
+.meta testfun
argument finds the minimum value.
-If a <testfun> argument is given, the two functions are equivalent.
-The <testfun> function must be callable with two arguments.
-If <testfun> behaves like a greater-than comparison, then find-max
-and find-min both return the maximum element. If <testfun>
+If a
+.meta testfun
+argument is given, the two functions are equivalent.
+The
+.meta testfun
+function must be callable with two arguments.
+If
+.meta testfun
+behaves like a greater-than comparison, then
+.code find-max
+and
+.code find-min
+both return the maximum element. If
+.meta testfun
behaves like a less-than comparison, then the functions return
the minimum element.
-The <keyfun> argument defaults to the identity function. Each element
-from sequence is passed through this one-argument function, and
+The
+.meta keyfun
+argument defaults to the
+.code identity
+function. Each element
+from
+.meta sequence
+is passed through this one-argument function, and
the resulting value is used in its place for the purposes of the
comparison. However, the original element is returned.
-.SS Function set-diff
-
-.TP
-Syntax:
- (set_diff <list1> <list2> [<testfun> [<keyfun>]])
-
-.TP
-Description:
-
-The set-diff function treats the lists <list1> and <list2> as if they were sets
-and computes the set difference: a list which contains those elements in
-<list1> which do not occur in <list2>.
-
-Element equivalence is determined by a combination of testfun and keyfun.
+.coNP Function @ set-diff
+.synb
+.mets (set-diff < seq1 < seq2 >> [ testfun <> [ keyfun ]])
+.syne
+.desc
+The
+.code set-diff
+function treats the sequences
+.meta seq1
+and
+.meta seq2
+as if they were sets
+and computes the set difference: a sequence which contains those elements in
+.meta seq1
+which do not occur in
+.metn seq2 .
+
+.code set-diff
+returns a sequence of the same kind as
+.metn seq1 .
+
+Element equivalence is determined by a combination of
+.meta testfun
+and
+.metn keyfun .
Elements are compared pairwise, and each element of a pair is passed through
-the keyfun function to produce a comparison value. The comparison values
-are compared with the testfun function. If keyfun is omitted, then the
-untransformed elements themselves are compared, and if testfun is omitted,
-then the equal function is used.
-
-If <list1> contains duplicate elements which do not occur in list2 (and
-thus are preserved in the set difference) then these duplicates appear
-in the resulting list. Furthermore, the order of the items from list1 is
-preserved.
-
-.SS Functions mapcar, mappend, mapcar* and mappend*
-
-.TP
-Syntax:
-
- (mapcar <function> <list>*)
- (mappend <function> <list>*)
- (mapcar* <function> <list>*)
- (mappend* <function> <list>*)
-
-.TP
-Description:
-
-When given only one argument, the mapcar function returns nil.
-The <function> is never called.
-
-When given two arguments, the mapcar function applies <function> to
-the elements of <list> and returns a list of the resulting values.
-Essentially, the list is filtered through the function.
-
-When additional lists are given as arguments, this filtering behavior is
-generalized in the following way: mapcar traverses the lists in parallel,
-taking a value from each list as an argument to the function. If there
-are two lists, the function is called with two arguments and so forth.
-The process is limited by the length of the shortest list.
-The return values of the function are collected into a new list which is
-returned.
-
-The mappend function works like mapcar, with the following difference.
-Rather than accumulating the values returned by the function into a list,
-mappend expects the items returned by the function to be lists which
-are catenated with append, and the resulting list is returned.
-That is to say, (mappend f a b c) is equivalent to
-(apply (fun append) (mapcar f a b c)).
+.meta keyfun
+function to produce a comparison value. The comparison values
+are compared using
+.metn testfun .
+If
+.meta keyfun
+is omitted, then the
+untransformed elements themselves are compared, and if
+.meta testfun
+is omitted,
+then the
+.code equal
+function is used.
-The mapcar* and mappend* functions work like mapcar and mappend, respectively.
+If
+.meta seq1
+contains duplicate elements which do not occur in
+.meta seq2
+(and thus are preserved in the set difference) then these duplicates appear
+in the resulting
+sequence. Furthermore, the order of the items from
+.meta seq1
+is preserved.
+
+.coNP Functions @, mapcar @ mappend @ mapcar* and @ mappend*
+.synb
+.mets (mapcar < function << sequence *)
+.mets (mappend < function << sequence *)
+.mets (mapcar* < function << sequence *)
+.mets (mappend* < function << sequence *)
+.syne
+.desc
+
+When given only one argument, the
+.code mapcar
+function returns
+.codn nil .
+.meta function
+is never called.
+
+When given two arguments, the
+.code mapcar
+function applies
+.meta function
+to each elements of
+.meta sequence
+and returns a sequence of the resulting values
+in the same order as the original values.
+The returned sequence is the same kind as
+.metn sequence ,
+if possible. If the accumulated values cannot be
+elements of that type of sequence, then a list is returned.
+
+When additional sequences are given as arguments, this filtering behavior is
+generalized in the following way:
+.code mapcar
+traverses the sequences in parallel,
+taking a value from each sequence as an argument to the function. If there
+are two lists,
+.meta function
+is called with two arguments and so forth.
+The traversal is limited by the length of the shortest sequence.
+The return values of the function are collected into a new sequence which is
+returned. The returned sequence is of the same kind as the leftmost
+input sequence, unless the accumulated values cannot be elements of that type of
+sequence, in which case a list is returned.
+
+The
+.code mappend
+function works like
+.codn mapcar ,
+with the following difference.
+Rather than accumulating the values returned by the function into a sequence,
+mappend expects the items returned by the function to be sequences which
+are catenated with
+.codn append ,
+and the resulting sequence is returned. The returned sequence is of the same
+kind as the leftmost input sequence, unless the values cannot be elements
+of that type of sequence, in which case a list is returned.
+
+The
+.code mapcar*
+and
+.code mappend*
+functions work like
+.code mapcar
+and
+.codn mappend ,
+respectively.
However, they return lazy lists rather than generating the entire
output list prior to returning.
-.TP
-Caveats:
-
-Like mappend, mappend* must "consume" empty lists. For instance,
-if the function being mapped puts out a sequence of nil values,
-then the result must be the empty list nil, because
-(append nil nil nil nil ...) is nil.
-
-Suppose that mappend* is used on inputs which are infinite lazy
-lists, such that the function returns nil values indefinitely.
+.TP* Caveats:
+
+Like
+.codn mappend ,
+.code mappend*
+must "consume" empty lists. For instance,
+if the function being mapped puts out a sequence of
+.codn nil s,
+then the result must be the empty list
+.codn nil ,
+because
+.code (append nil nil nil nil ...)
+is
+.codn nil .
+
+But suppose that
+.code mappend*
+is used on inputs which are infinite lazy
+lists, such that the function returns
+.code nil
+values indefinitely.
For instance:
+.cblk
;; Danger: infinite loop!!!
(mappend* (fun identity) (repeat '(nil)))
+.cble
-The mappend* function is caught in a loop trying to consume
-and squash an infinite stream of nil values.
-
-.TP
-Examples:
+The
+.code mappend*
+function is caught in a loop trying to consume
+and squash an infinite stream of
+.codn nil s,
+and so doesn't return.
+.TP* Examples:
+.cblk
;; multiply every element by two
(mapcar (lambda (item) (* 2 item)) '(1 2 3)) -> (4 6 8)
@@ -8309,66 +13566,99 @@ Examples:
;; take just the even numbers
(mappend (lambda (item) (if (evenp x) (list x))) '(1 2 3 4 5))
-> (2 4)
-
-.SS Function mapdo
-
-.TP
-Syntax:
-
- (mapdo <function> <sequence>*)
-
-.TP
-Description:
-
-The mapdo function is similar to mapcar, but always returns nil. It is useful
-when <function> performs some kind of side effect, hence the "do" in the name,
+.cble
+
+.coNP Function @ mapdo
+.synb
+.mets (mapdo < function << sequence *)
+.syne
+.desc
+The
+.code mapdo
+function is similar to
+.codn mapcar ,
+but always returns
+.codn nil .
+It is useful
+when
+.meta function
+performs some kind of side effect, hence the "do" in the name,
which is a mnemonic for the execution of imperative actions.
-When only the <function> argument is given, the function is never called,
-and nil is returned.
-
-If a single <sequence> argument is given, then mapdo iterates over
-<sequence>, invoking <function> on each element.
+When only the
+.meta function
+argument is given,
+.meta function
+is never called,
+and
+.code nil
+is returned.
-If two or more <sequence> arguments are given, then mapdo iterates over
+If a single
+.meta sequence
+argument is given, then
+.code mapdo
+iterates over
+.metn sequence ,
+invoking
+.meta function
+on each element.
+
+If two or more
+.meta sequence
+arguments are given, then
+.code mapdo
+iterates over
the sequences in parallel, extracting parallel tuples of items. These
-tuples are passed as arguments to <function>, which must accept as many
+tuples are passed as arguments to
+.metn function,
+which must accept as many
arguments as there are sequences.
-.SS Functions transpose and zip
-
-.TP
-Syntax:
-
- (transpose <sequence>)
- (zip <sequence>*)
-
-.TP
-Description:
-
-The transpose function performs a transposition on <sequence>. This means that the
-elements of <sequence> must be sequences. These sequences are understood to be
+.coNP Functions @ transpose and @ zip
+.synb
+.mets (transpose << sequence )
+.mets (zip << sequence *)
+.syne
+.desc
+The
+.code transpose
+function performs a transposition on
+.metn sequence .
+This means that the
+elements of
+.meta sequence
+must be sequences. These sequences are understood to be
columns; transpose exchanges rows and columns, returning a sequence of the rows
which make up the columns. The returned sequence is of the same kind as
-<sequence>, and the rows are also the same kind of sequence as the first column
+.metn sequence ,
+and the rows are also the same kind of sequence as the first column
of the original sequence. The number of rows returned is limited by the
shortest column among the sequences.
-All of the input sequences (the elements of <sequence>) must have elements
+All of the input sequences (the elements of
+.metn sequence)
+must have elements
which are compatible with the first sequence. This means that if the first
-element of <sequence> is a string, then the remaining sequences must be
+element of
+.meta sequence
+is a string, then the remaining sequences must be
strings, or else sequences of characters, or of strings.
-The zip function takes variable arguments, and is equivalent to calling
-transpose on a list of the arguments. The following equivalences hold:
+The
+.code zip
+function takes variable arguments, and is equivalent to calling
+.code transpose
+on a list of the arguments. The following equivalences hold:
+.synb
(zip . x) <--> (transpose x)
[apply zip x] <--> (transpose x)
+.syne
-.TP
-Examples:
-
+.TP* Examples:
+.cblk
;; transpose list of lists
(transpose '((a b c) (c d e))) -> ((a c) (b d) (c e))
@@ -8385,34 +13675,51 @@ Examples:
(transpose #("abc" "def" ("UV" "XY" "WZ"))) -> #("adUV" "beXY" "cfWZ")
(zip '(a b c) '(c d e)) -> ((a c) (b d) (c e))
-
-.SS Function interpose
-
-.TP
-Syntax:
-
- (interpose <sep> <sequence>)
-
-.TP
-Description:
-
-The interpose function returns a sequence of the same type as <sequence>,
-in which the elements from <sequence> appear with the <sep> value inserted
+.cble
+
+.coNP Function @ interpose
+.synb
+.mets (interpose < sep << sequence )
+.syne
+.desc
+The
+.code interpose
+function returns a sequence of the same type as
+.metn sequence ,
+in which the elements from
+.meta sequence
+appear with the
+.meta sep
+value inserted
between them.
-If <sequence> is an empty sequence or a sequence of length 1, then a
-sequence identical to <sequence> is returned. It may be a copy of <sequence>
-or it may be <sequence> itself.
-
-If <sequence> is a character string, then the value <sep> must be a character.
+If
+.meta sequence
+is an empty sequence or a sequence of length 1, then a
+sequence identical to
+.meta sequence
+is returned. It may be a copy of
+.meta sequence
+or it may be
+.meta sequence
+itself.
-It is permissible for <sequence>, or for a suffix of <sequence> to be a lazy
+If
+.meta sequence
+is a character string, then the value
+.meta sep
+must be a character.
+
+It is permissible for
+.metn sequence ,
+or for a suffix of
+.meta sequence
+to be a lazy
list, in which case interpose returns a lazy list, or a list with a lazy
suffix.
-.SS
-Examples:
-
+.TP* Examples:
+.cblk
(interpose #\e- "xyz") -> "x-y-z"
(interpose t nil) -> nil
(interpose t #()) -> #()
@@ -8420,94 +13727,157 @@ Examples:
(interpose t (range 0 0)) -> (0)
(interpose t (range 0 1)) -> (0 t 1)
(interpose t (range 0 2)) -> (0 t 1 t 2)
-
-.SS Functions conses and conses*
-
-.TP
-Syntax:
-
- (conses <list>)
- (conses* <list>)
-
-.TP
-Description:
-
+.cble
+
+.coNP Functions @ conses and @ conses*
+.synb
+.mets (conses << list )
+.mets (conses* << list )
+.syne
+.desc
These functions return a list whose elements are the conses which make
-up <list>. The conses* function does this in a lazy way, avoiding the
-computation of the entire list: it returns a lazy list of the conses of <list>.
-The conses function computes the entire list before returning.
-
-The input <list> may be proper or improper.
-
-The first cons of a list is that list itself. The second cons is the rest
-of the list, or (cdr <list>). The third cons is (cdr (cdr <list>)) and so on.
-
-.TP
-Example:
-
+up
+.metn list .
+The
+.code conses*
+function does this in a lazy way, avoiding the
+computation of the entire list: it returns a lazy list of the conses of
+.metn list .
+The
+.code conses
+function computes the entire list before returning.
+
+The input
+.meta list
+may be proper or improper.
+
+The first cons of
+.meta list
+is that
+.meta list
+itself. The second cons is the rest
+of the list, or
+.cblk
+.meti (cdr << list ).
+.cble
+The third cons is
+.cblk
+.meti (cdr (cdr << list ))
+.cble
+and so on.
+
+.TP* Example:
+.cblk
(conses '(1 2 3)) -> ((1 2 3) (2 3) (3))
+.cble
-.TP
-Dialect Note:
+.TP* "Dialect Note:"
-These functions are useful for simulating the maplist function found in
-other dialects like Common Lisp.
+These functions are useful for simulating the
+.code maplist
+function found in other dialects like Common Lisp.
-TXR Lisp's (conses x) can be expressed in Common Lisp as
-(maplist #'identity x).
+TXR Lisp's
+.code (conses x)
+can be expressed in Common Lisp as
+.codn (maplist #'identity x) .
-Conversely, the Common Lisp operation (maplist function list) can be computed
-in TXR Lisp as (mapcar function (conses list)).
+Conversely, the Common Lisp operation
+.code (maplist function list)
+can be computed in TXR Lisp as
+.codn (mapcar function (conses list)) .
More generally, the Common Lisp operation
+.cblk
(maplist function list0 list1 ... listn)
-
-can be expressed as:
-
- (mapcar function (conses list0) (conses list1) ... (conses listn))
-
-.SS Functions apply and iapply
-
-.TP
-Syntax:
+.cble
- (apply <function> [ <arg>* <trailing-args> ])
- (iapply <function> [ <arg>* <trailing-args> ])
-
-.TP
-Description:
-
-The apply function invokes <function>, optionally passing to it an argument
-list. The return value of the apply call is that of <function>.
-
-If no arguments are present after <function>, then <function> is invoked
-without arguments.
+can be expressed as:
-If one argument is present after <function>, then it is interpreted as
-<trailing-args>. If this is a sequence (a list, vector or string),
+.cblk
+ (mapcar function (conses list0)
+ (conses list1) ... (conses listn))
+.cble
+
+.coNP Functions @ apply and @ iapply
+.synb
+.mets (apply < function <> [ arg * << trailing-args ])
+.mets (iapply < function <> [ arg * << trailing-args ])
+.syne
+.desc
+The
+.code apply
+function invokes
+.metn function ,
+optionally passing to it an argument
+list. The return value of the
+.code apply
+call is that of
+.metn function .
+
+If no arguments are present after
+.metn function ,
+then
+.meta function
+is invoked without arguments.
+
+If one argument is present after
+.metn function ,
+then it is interpreted as
+.metn trailing-args .
+If this is a sequence (a list, vector or string),
then the elements of the sequence are passed as individual arguments to
-<function>. If <trailing-args> is not a sequence, then the function is invoked
-with an improper argument list, terminated by the <trailing-args> atom.
-
-If two or more arguments are present after <function>, then the last of
-these arguments is interpreted as <trailing-args>. The previous arguments
-represent leading arguments which are applied to <function>, prior to the
-arguments taken from <trailing-args>.
-
-The iapply function ("improper apply") is similar to apply, except with regard
-to the treatment of <trailing-args>. Firstly, under iapply, if <trailing-args>
-is an atom other than nil (possibly a sequence, such as a vector or string),
-then it is treated as an ordinary argument: <function> is invoked with a proper
-argument list, whose last element is <trailing-args>. Secondly, if
-<trailing-args> is a list, but an improper list, then the terminating atom of
-<trailing-args> becomes an ordinary argument. Thus, in all possible cases,
-iapply treats an extra non-nil atom as an argument, and never calls
-<function> with an improper argument list.
-
-.TP
-Examples:
-
+.metn function .
+If
+.meta trailing-args
+is not a sequence, then
+.meta function
+is invoked
+with an improper argument list, terminated by the
+.meta trailing-args
+atom.
+
+If two or more arguments are present after
+.metn function ,
+then the last of these arguments is interpreted as
+.metn trailing-args .
+The previous arguments represent leading arguments which are applied to
+.metn function ,
+prior to the arguments taken from
+.metn trailing-args .
+
+The
+.code iapply
+function ("improper apply") is similar to
+.codn apply ,
+except with regard to the treatment of
+.metn trailing-args .
+Firstly, under
+.codn iapply ,
+if
+.meta trailing-args
+is an atom other than
+.code nil
+(possibly a sequence, such as a vector or string),
+then it is treated as an ordinary argument:
+.meta function
+is invoked with a proper argument list, whose last element is
+.metn trailing-args .
+Secondly, if
+.meta trailing-args
+is a list, but an improper list, then the terminating atom of
+.meta trailing-args
+becomes an ordinary argument. Thus, in all possible cases,
+.code iapply
+treats an extra
+.cod2 non- nil
+atom as an argument, and never calls
+.meta function
+with an improper argument list.
+
+.TP* Examples:
+.cblk
;; '(1 2 3) becomes arguments to list, thus (list 1 2 3).
(apply (fun list) '(1 2 3)) -> (1 2 3)
@@ -8519,94 +13889,175 @@ Examples:
;; "abc" is separated into characters which become arguments of list
(apply (fun list) "abc") -> (#\ea #\eb #\ec)
+.cble
-.TP
-Dialect Note:
-
+.TP* "Dialect Note:"
Note that some uses of this function that are necessary in other Lisp dialects
are not necessary in TXR Lisp. The reason is that in TXR Lisp, improper list
syntax is accepted as a compound form, and performs application:
+.cblk
(foo a b . x)
-
-Here, the variables a and b supply the first two arguments for foo. In
-the dotted position, x must evaluate to a list or vector. The list or
-vector's elements are pulled out and treated as additional arguments for foo.
-Of course, this syntax can only be used if x is a symbolic form or an atom. It
-cannot be a compound form.
-
-.SS Functions reduce-left and reduce-right
-
-.TP
-Syntax:
-
- (reduce-left <binary-function> <list> [ <init-value> [ <key-function> ]])
- (reduce-right <binary-function> <list> [ <init-value> [ <key-function> ]])
-
-.TP
-Description:
-
-The reduce-left and reduce-right functions reduce lists of operands specified
-by <list> and <init-value> to a single value by the repeated application of
-<binary-function>.
-
-An effective list of operands is formed by combining <list> and
-<init-value>. If <key-function> is specified, then the items of <list> are
-mapped to a new values through <key-function>. If <init-value> is supplied,
-then in the case of reduce-left, the effective list of operands is formed by
-prepending <init-value> to <list>. In the case of reduce-right, the effective
-operand list is produced by appending <init-value> to <list>.
+.cble
+
+Here, the variables
+.code a
+and
+.code b
+supply the first two arguments for
+.codn foo .
+In
+the dotted position,
+.code x
+must evaluate to a list or vector. The list or
+vector's elements are pulled out and treated as additional arguments for
+.codn foo .
+Of course, this syntax can only be used if
+.code x
+is a symbolic form or an atom. It
+cannot be a compound form, because
+.code (foo a b . (x))
+and
+.code (foo a b x)
+are equivalent structures.
+
+.coNP Functions @ reduce-left and @ reduce-right
+.synb
+.mets (reduce-left < binary-function < list
+.mets \ \ \ \ \ \ \ \ \ \ \ \ >> [ init-value <> [ key-function ]])
+
+.mets (reduce-right < binary-function < list
+.mets \ \ \ \ \ \ \ \ \ \ \ \ \ >> [ init-value <> [ key-function ]])
+.syne
+.desc
+The
+.code reduce-left
+and
+.code reduce-right
+functions reduce lists of operands specified
+by
+.meta list
+and
+.meta init-value
+to a single value by the repeated application of
+.metn binary-function .
+
+An effective list of operands is formed by combining
+.meta list
+and
+.metn init-value .
+If
+.meta key-function
+is specified, then the items of
+.meta list
+are
+mapped to a new values through
+.metn key-function .
+If
+.meta init-value
+is supplied,
+then in the case of
+.codn reduce-left ,
+the effective list of operands is formed by
+prepending
+.meta init-value
+to
+.metn list .
+In the case of
+.codn reduce-right ,
+the effective operand list is produced by appending
+.meta init-value
+to
+.metn list .
The production of the effective list can be expressed like this,
though this is not to be understood as the actual implementation:
- ;; reduce-left
- (let ((eff-list (append (if init-value-present (list init-value))
- [mapcar (or key-function identity) list])))
+.cblk
+ (append (if init-value-present (list init-value))
+ [mapcar (or key-function identity) list]))))
+.cble
-In the reduce-right case, the arguments to append are reversed.
+In the
+.code reduce-right
+case, the arguments to
+.code append
+are reversed.
-If the effective list of operands is empty, then <binary-function> is called
+If the effective list of operands is empty, then
+.meta binary-function
+is called
with no arguments at all, and its value is returned. This is the only
-case in which <binary-function> is called with no arguments; in all
+case in which
+.meta binary-function
+is called with no arguments; in all
remaining cases, it is called with two arguments.
If the effective list contains one item, then that item is returned.
Otherwise, the effective list contains two or more items, and is decimated as
-follows.
-
-Note that an <init-value> specified as nil is not the same as a missing
-<init-value>; this means that the initial value is the object nil. Omitting
-<init-value> is the same as specifying a value of : (the colon symbol).
-It is possible to specify <key-function> while omitting an <init-value>
-argument. This is achieved by explicitly specifying : as the <init-value>
+follows.
+
+Note that an
+.meta init-value
+specified as
+.code nil
+is not the same as a missing
+.metn init-value ;
+this means that the initial value is the object
+.codn nil .
+Omitting
+.meta init-value
+is the same as specifying a value of
+.code :
+(the colon symbol).
+It is possible to specify
+.meta key-function
+while omitting an
+.meta init-value
+argument. This is achieved by explicitly specifying
+.code :
+as the
+.meta init-value
argument.
-Under reduce-left, the leftmost pair of operands is removed
-from the list and passed as arguments to <binary-function>, in the same order
+Under
+.codn reduce-left ,
+the leftmost pair of operands is removed
+from the list and passed as arguments to
+.metn binary-function ,
+in the same order
that they appear in the list, and the resulting value initializes an
-accumulator. Then, for each remaining item in the list, <binary-function> is
-invoked on two arguments: the current accumulator value, and the next element
+accumulator. Then, for each remaining item in the list,
+.meta binary-function
+is invoked on two arguments: the current accumulator value, and the next element
from the list. After each call, the accumulator is updated with the return
-value of <binary-function>. The final value of the accumulator is returned.
+value of
+.metn binary-function .
+The final value of the accumulator is returned.
-Under reduce-right, the list is processed right to left. The rightmost
+Under
+.codn reduce-right ,
+the list is processed right to left. The rightmost
pair of elements in the effective list is removed, and passed as arguments to
-<binary-function>, in the same order that they appear in the list. The
+.metn binary-function ,
+in the same order that they appear in the list. The
resulting value initializes an accumulator. Then, for each remaining item in
-the list, <binary-function> is invoked on two arguments: the
+the list,
+.meta binary-function
+is invoked on two arguments: the
next element from the list, in right to left order, and the current
accumulator value. After each call, the accumulator is updated with the return
-value of <binary-function>. The final value of the accumulator is returned.
-
-.TP
-Examples:
+value of
+.metn binary-function .
+The final value of the accumulator is returned.
+.TP* Examples:
+.cblk
;;; effective list is (1) so 1 is returned
- (reduce-left (fun +) () 1 nil) -> 1
+ (reduce-left (fun +) () 1 nil) -> 1
- ;;; computes (- (- (- 0 1) 2) 3)
+ ;;; computes (- (- (- 0 1) 2) 3)
(reduce-left (fun -) '(1 2 3) 0 nil) -> -6
;;; computes (- 1 (- 2 (- 3 0)))
@@ -8618,90 +14069,169 @@ Examples:
;;; computes 1 because the effective list is empty
;;; and so * is called with no arguments, which yields 1.
(reduce-left (fun *) nil)
-
-.SS Function some, all and none
-
-.TP
-Syntax:
-
- (some <list> [ <predicate-fun> [<key-fun>] ])
- (all <list> [ <predicate-fun> [<key-fun>] ])
- (none <list> [ <predicate-fun> [<key-fun>] ])
-
-.TP
-Description
-
-The some, all and none functions apply a predicate test function
-<predicate-fun> over a list of elements. If the argument <key-fun> is
-specified, then values <list> are passed into <key-fun>, and <predicate-fun> is
-applied to the resulting values. If <key-fun> is omitted, the behavior is
-as if <key-fun> is the identity function. If <predicate-fun> is omitted,
-the behavior is as if <predicate-fun> is the identity function.
+.cble
+
+.coNP Function @, some @ all and @ none
+.synb
+.mets (some < sequence >> [ predicate-fun <> [ key-fun ]])
+.mets (all < sequence >> [ predicate-fun <> [ key-fun ]])
+.mets (none < sequence >> [ predicate-fun <> [ key-fun ]])
+.syne
+.desc
+The
+.codn some ,
+.code all
+and
+.code none
+functions apply a predicate test function
+.meta predicate-fun
+over a list of elements. If the argumenti
+.meta key-fun
+is
+specified, then elements of
+.meta sequence
+are passed into
+.metn key-fun ,
+and
+.meta predicate-fun
+is
+applied to the resulting values. If
+.meta key-fun
+is omitted, the behavior is
+as if
+.meta key-fun
+is the identity function. If
+.meta predicate-fun
+is omitted,
+the behavior is as if
+.meta predicate-fun
+is the identity function.
These functions have short-circuiting semantics and return conventions similar
to the and and or operators.
-The some function applies <predicate-fun> to successive values
-produced by retrieving elements of <list> and processing them through
-<key-fun>. If the list is empty, it returns nil. Otherwise it returns the
-first non-nil return value returned by a call to <predicate-fun> and
-stops evaluating more elements. If <predicate-fun> returns nil for all
-elements, it returns nil.
-
-The all function applies <predicate-fun> to successive values
-produced by retrieving elements of <list> and processing them through
-<key-fun>. If the list is empty, it returns t. Otherwise, if
-<predicate-fun> yields nil for any value, the all function immediately
-returns without invoking <predicate-fun> on any more elements.
+The some function applies
+.meta predicate-fun
+to successive values
+produced by retrieving elements of
+.meta list
+and processing them through
+.metn key-fun .
+If the list is empty, it returns
+.codn nil .
+Otherwise it returns the
+first
+.cod2 non- nil
+return value returned by a call to
+.meta predicate-fun
+and
+stops evaluating more elements. If
+.meta predicate-fun
+returns
+.code nil
+for all
+elements, it returns
+.metn nil .
+
+The
+.code all
+function applies
+.meta predicate-fun
+to successive values
+produced by retrieving elements of
+.meta list
+and processing them through
+.metn key-fun .
+If the list is empty, it returns
+.codn t .
+Otherwise, if
+.meta predicate-fun
+yields
+.code nil
+for any value, the
+.cod all
+function immediately
+returns without invoking
+.meta predicate-fun
+on any more elements.
If all the elements are processed, then the all function returns
-the value which <predicate-fun> yielded for the last element.
-
-The none function applies <predicate-fun> to successive values
-produced by retrieving elements of <list> and processing them through
-<key-fun>. If the list is empty, it returns t. Otherwise, if
-<predicate-fun> yields non-nil for any value, the none function
-immediately returns nil. If <predicate-fun> yields nil for all
-values, the none function returns t.
-
-.TP
-Examples:
-
+the value which
+.meta predicate-fun
+yielded for the last element.
+
+The
+.code none
+function applies
+.meta predicate-fun
+to successive values
+produced by retrieving elements of
+.meta list
+and processing them through
+.metn key-fun .
+If the list is empty, it returns
+.codn t .
+Otherwise, if
+.meta predicate-fun
+yields
+.cod2 non- nil
+for any value, the none function
+immediately returns nil. If
+.meta predicate-fun
+yields nil for all
+values, the none function returns
+.codn t .
+
+.TP* Examples:
+
+.cblk
;; some of the integers are odd
[some '(2 4 6 9) oddp] -> t
;; none of the integers are even
[none '(1 3 4 7) evenp] -> t
-
-.SS Function multi
-
-.TP
-Syntax:
-
- (multi <function> <list>*)
-
-.TP
-Description:
-
-The multi function distributes an arbitrary list processing function <multi>
-over multiple lists given by the <list> arguments.
-
-The <list> arguments are first transposed into a single list of tuples. Each
-successive element of this transposed list consists of a combination of the
+.cble
+
+.coNP Function @ multi
+.synb
+.mets (multi < function << list *)
+.syne
+.desc
+The
+.code multi
+function distributes an arbitrary list processing function
+.meta multi
+over multiple lists given by the
+.meta list
+arguments.
+
+The
+.meta list
+arguments are first transposed into a single list of tuples. Each
+successive element of this transposed list consists of a tuple of the
successive items from the lists. The length of the transposed list is that
-of the shortest <list> argument.
+of the shortest
+.meta list
+argument.
-The transposed list is then passed to <function> as an argument.
+The transposed list is then passed to
+.meta function
+as an argument.
-The <function> is expected to produce a list of tuples, which are transposed
+The
+.meta functio
+is expected to produce a list of tuples, which are transposed
again to produce a list of lists which is then returned.
-Conceptually, the input lists are columns and <function> is invoked on
-a list of the rows formed from these columns. The output of <function>
+Conceptually, the input lists are columns and
+.meta function
+is invoked on
+a list of the rows formed from these columns. The output of
+.meta function
is a transformed list of rows which is reconstituted into a list of columns.
-.TP
-Example:
+.TP* Example:
+.cblk
;; Take three lists in parallel, and remove from all of them
;; them the element at all positions where the third list
;; has an element of 20.
@@ -8719,8 +14249,9 @@ Example:
;; expression can be simplified using the ap operator:
;;
;; (op remove-if (ap eql @3 20))
+.cble
-.SH ASSOCIATION LISTS
+.SS* Association Lists
Association lists are ordinary lists formed according to a special convention.
Firstly, any empty list is a valid association list. A non-empty association
@@ -8728,241 +14259,299 @@ list contains only cons cells as the key elements. These cons cells are
understood to represent key/value associations, hence the name "association
list".
-.SS Function assoc
-
-.TP
-Syntax:
-
- (assoc <key> <alist>)
-
-.TP
-Description:
-
-The assoc function searches an association list <alist> for a cons cell whose
-car field is equivalent to <key> (with equality determined by the equal
-function). The first such cons is returned. If no such cons is found, nil is
-returned.
-
-.SS Function assql
-
-.TP
-Syntax:
-
- (assql <key> <alist>)
-
-.TP
-Description:
-
-The assql function is just like assoc, except that the equality test
-is determined using the eql function rather than equal.
-
-.SS Function acons
-
-.TP
-Syntax:
-
- (acons <car> <cdr> <alist>)
-
-.TP
-Description:
+.coNP Function @ assoc
+.synb
+.mets (assoc < key << alist )
+.syne
+.desc
+The
+.code assoc
+function searches an association list
+.meta alist
+for a cons cell whose
+car field is equivalent to
+.meta key
+(with equality determined by the equal
+function). The first such cons is returned. If no such cons is found,
+.code nil
+is returned.
-The acons function constructs a new alist by consing a new cons to the
-front of <alist>. The following equivalence holds:
+.coNP Function @ assql
+.synb
+.mets (assql < key << alist )
+.syne
+.desc
+The
+.code assql
+function is just like
+.codn assoc ,
+except that the equality test
+is determined using the
+.code eql
+function rather than
+.codn equal .
+
+.coNP Function @ acons
+.synb
+.mets (acons < car < cdr << alist )
+.syne
+.desc
+
+The
+.code acons
+function constructs a new alist by consing a new cons to the
+front of
+.metn alist .
+The following equivalence holds:
+.cblk
(acons car cdr alist) <--> (cons (cons car cdr) alist)
-
-.SS Function acons-new
-
-.TP
-Syntax:
-
- (acons-new <car> <cdr> <alist>)
-
-.TP
-Description:
-
-The acons-new function searches <alist>, as if using the assoc function,
+.cble
+
+.coNP Function @ acons-new
+.synb
+.mets (acons-new < car < cdr << alist )
+.syne
+.desc
+
+The
+.code acons-new
+function searches
+.metn alist ,
+as if using the assoc function,
for an existing cell which matches the key provided by the car argument.
-If such a cell exists, then its cdr field is overwritten with the <cdr>
-argument, and then the list is returned. If no such cell exists, then
+If such a cell exists, then its cdr field is overwritten with the
+.meta cdr
+argument, and then the
+.meta alist
+is returned. If no such cell exists, then
a new list is returned by adding a new cell to the input list consisting
-of the <car> and <cdr> values, as if by the acons function.
-
-.SS Function aconsql-new
-
-.TP
-Syntax:
-
- (aconsql-new <car> <cdr> <alist>)
-
-.TP
-Description:
+of the
+.meta car
+and
+.meta cdr
+values, as if by the
+.code acons
+function.
-This function is like acons-new, except that the eql function is used
+.coNP Function @ aconsql-new
+.synb
+.mets (aconsql-new < car < cdr << alist )
+.syne
+.desc
+This function is like
+.codn acons-new ,
+except that the
+.code
+eql
+function is used
for equality testing. Thus, the list is searched for an existing cell
-as if using the assql function rather than assoc.
-
-.SS Function alist-remove
-
-.TP
-Syntax:
-
- (alist-remove <alist> <keys>)
-
-.TP
-Description:
-
-The alist-remove function takes association list <alist> and produces a
+as if using the
+.code assql
+function rather than
+.codn assoc .
+
+.coNP Function @ alist-remove
+.synb
+.mets (alist-remove < alist << keys )
+.syne
+.desc
+The
+.code alist-remove
+function takes association list
+.meta alist
+and produces a
duplicate from which cells matching the specified keys have been removed. The
-<keys> argument is a list of the keys not to appear in the output list.
-
-.SS Function alist-nremove
-
-.TP
-Syntax:
-
- (alist-nremove <alist> <keys>)
-
-.TP
-Description:
-
-The alist-nremove function is like alist-remove, but potentially destructive.
-The input list <alist> may be destroyed and its structural material re-used to
+.meta keys
+argument is a list of the keys not to appear in the output list.
+
+.coNP Function @ alist-nremove
+.synb
+.mets (alist-nremove < alist << keys )
+.syne
+.desc
+The
+.code alist-nremove
+function is like
+.codn alist-remove ,
+but potentially destructive.
+The input list
+.meta alist
+may be destroyed and its structural material re-used to
form the output list. The application should not retain references to the input
list.
-.SS Function copy-alist
-
-.TP
-Syntax:
-
- (copy-alist <alist>)
-
-.TP
-Description:
-
-The copy-alist function duplicates <alist>. Unlike copy-list, which
-only duplicates list structure, copy-alist also duplicates each cons
+.coNP Function @ copy-alist
+.synb
+.mets (copy-alist << alist )
+.syne
+.desc
+The
+.code copy-alist
+function duplicates
+.codn alist .
+Unlike
+.codn copy-list ,
+which only duplicates list structure,
+.code copy-alist
+also duplicates each cons
cell of the input alist. That is to say, each element of the output list
-is produced as if by the copy-cons function applied to the corresponding
+is produced as if by the
+.code copy-cons
+function applied to the corresponding
element of the input list.
-.SH PROPERTY LISTS
-
-.SS Function prop
-
-.TP
-Syntax:
-
- (prop <plist> <key>)
-
-.TP
-Description:
-
+.SS* Property Lists
+.coNP Function @ prop
+.synb
+.mets (prop < plist << key )
+.syne
+.desc
A property list a flat list of even length consisting of interleaved
pairs of property names (usually symbols) and their values (arbitrary
objects). An example property list is (:a 1 :b "two") which contains
two properties, :a having value 1, and :b having value "two".
-The prop function searches property list <plist> for key <key>. If
-the key is found, then the value next to it is returned. Otherwise
-nil is returned.
-
-It is ambiguous whether nil is returned due to the property not being
-found, or due to the property being present with a nil value.
-
-.SH LIST SORTING
-
-.SS Function merge
-
-.TP
-Syntax:
-
- (merge <list1> <list2> <lessfun> [<keyfun>])
+The
+.code prop
+function searches property list
+.meta plist
+for key
+.metn key .
+If the key is found, then the value next to it is returned. Otherwise
+.code nil
+is returned.
-.TP
-Description:
+It is ambiguous whether
+.code nil
+is returned due to the property not being
+found, or due to the property being present with a
+.code nil
+value.
-The merge function merges two sorted lists <list1> and <list2> into a single
-sorted list. The semantics and defaulting behavior of the <lessfun> and
-<keyfun> arguments are the same as those of the sort function. The input lists
+.SS* List Sorting
+.coNP Function @ merge
+.synb
+.mets (merge < list1 < list2 < lessfun <> [ keyfun ])
+.syne
+.desc
+The
+.code merge
+function merges two sorted lists
+.meta list1
+and
+.meta list2
+into a single
+sorted list. The semantics and defaulting behavior of the
+.meta lessfun
+and
+.meta keyfun
+arguments are the same as those of the sort function. The input lists
are assumed to be sorted according to these functions.
This function is destructive. The application should not retain references to
the input lists, since the output list is formed out of the structure of the
input lists.
-.SS Function multi-sort
-
-.TP
-Syntax:
-
- (multi-sort <columns> <less-funcs> [<key-funcs>])
-
-.TP
-Description:
-
-The multi-sort function regards a list of lists to be the columns of a
+.coNP Function @ multi-sort
+.synb
+.mets (multi-sort < columns < less-funcs <> [ key-funcs ])
+.syne
+.desc
+The
+.code multi-sort
+function regards a list of lists to be the columns of a
database. The corresponding elements from each list constitute a record.
These records are to be sorted, producing a new list of lists.
-The <columns> argument supplies the list of lists which comprise the columns of
+The
+.meta columns
+argument supplies the list of lists which comprise the columns of
the database. The lists should ideally be of the same length. If the lists are
of different lengths, then the shortest list is taken to be the length of the
database. Excess elements in the longer lists are ignored, and do not appear in
the sorted output.
-The <less-funcs> argument supplies a list of comparison functions which are
+The
+.meta less-funcs
+argument supplies a list of comparison functions which are
applied to the columns. Successive functions correspond to successive
-columns. If <less-funcs> is an empty list, then the sorted database will
-emerge in the original order. If <less-funcs> contains exactly one function,
+columns. If
+.meta less-funcs
+is an empty list, then the sorted database will
+emerge in the original order. If
+.meta less-funcs
+contains exactly one function,
then the rows of the database is sorted according to the first column. The
-remaining columns simply follow their row. If <less-funcs> contains more than
+remaining columns simply follow their row. If
+.meta less-funcs
+contains more than
one function, then additional columns are taken into consideration if the items
-in the previous columns compare equal. For instance if two elements from column
-one compare equal, then the corresponding second column elements are compared
+in the previous columns compare
+.codn equal .
+For instance if two elements from column
+one compare
+.codn equal ,
+then the corresponding second column elements are compared
using the second column comparison function.
-The optional <key-funcs> argument supplies transformation functions through
+The optional
+.meta key-funcs
+argument supplies transformation functions through
which column entries are converted to comparison keys, similarly to the single
key function used in the sort function and others. If there are more key
functions than less functions, the excess key functions are ignored.
-.SH LAZY LISTS AND LAZY EVALUATION
-
-.SS Function make-lazy-cons
-
-.TP
-Syntax:
-
-(make-lazy-cons <function>)
-
-.TP
-Description:
-
-The function make-lazy-cons makes a special kind of cons cell called a lazy
+.SS* Lazy Lists and Lazy Evaluation
+.coNP Function @ make-lazy-cons
+.synb
+.mets (make-lazy-cons << function )
+.syne
+.desc
+The function
+.code make-lazy-cons
+makes a special kind of cons cell called a lazy
cons, or lcons. Lazy conses are useful for implementing lazy lists.
Lazy lists are lists which are not allocated all at once. Rather,
their elements materialize when they are accessed, like
magic stepping stones appearing under one's feet out of thin air.
-A lazy cons has "car" and "cdr" fields like a regular cons, and those
-fields are initialized to nil when the lazy cons is created. A lazy cons also
-has an update function, the one which is provided as the <function>
-argument to make-lazy-cons.
-
-When either the car and cdr fields of a cons are accessed for the first time,
+A lazy cons has
+.code car
+and
+.code cdr
+fields like a regular cons, and those
+fields are initialized to
+.code nil
+when the lazy cons is created. A lazy cons also
+has an update function, the one which is provided as the
+.meta function
+argument to
+.codn make-lazy-cons .
+
+When either the
+.code car
+and
+.code cdr
+fields of a cons are accessed for the first time,
the function is automatically invoked first. That function has the opportunity
-to initialize the car and cdr fields. Once the function is called, it is removed
+to initialize the
+.code car
+and
+.code cdr
+fields. Once the function is called, it is removed
from the lazy cons: the lazy cons no longer has an update function.
-To continue a lazy list, the function can make another call to make-lazy-cons
-and install the resulting cons as the cdr of the lazy cons.
+To continue a lazy list, the function can make another call to
+.code make-lazy-cons
+and install the resulting cons as the
+.code cdr
+of the lazy cons.
-.TP
-Example:
+.TP* Example:
+.cblk
;;; lazy list of integers between min and max
(defun integer-range (min max)
(let ((counter min))
@@ -8970,116 +14559,156 @@ Example:
;; otherwise return a lazy list
(if (> min max)
nil
- (make-lazy-cons (lambda (lcons)
- ;; install next number into car
- (rplaca lcons counter)
- ;; now deal wit cdr field
- (cond
- ;; max reached, terminate list with nil!
- ((eql counter max)
- (rplacd lcons nil))
- ;; max not reached: increment counter
- ;; and extend with another lazy cons
- (t
- (inc counter)
- (rplacd lcons (make-lazy-cons
- (lcons-fun lcons))))))))))
-
-.SS Function lconsp
-
-.TP
-Syntax:
-
- (lconsp <value>)
-
-.TP
-Description:
-
-The lconsp function returns t if <value> is a lazy cons cell. Otherwise
-it returns nil, even if <value> is an ordinary cons cell.
-
-.SS Function lcons-fun
-
-.TP
-Syntax:
-
-(lcons-fun <lazy-cons>)
-
-.TP
-Description:
-
-The lcons-fun function retrieves the update function of a lazy cons.
+ (make-lazy-cons
+ (lambda (lcons)
+ ;; install next number into car
+ (rplaca lcons counter)
+ ;; now deal wit cdr field
+ (cond
+ ;; max reached, terminate list with nil!
+ ((eql counter max)
+ (rplacd lcons nil))
+ ;; max not reached: increment counter
+ ;; and extend with another lazy cons
+ (t
+ (inc counter)
+ (rplacd lcons (make-lazy-cons
+ (lcons-fun lcons))))))))))
+.cble
+
+.coNP Function @ lconsp
+.synb
+.mets (lconsp << value )
+.desc
+The
+.code lconsp
+function returns
+.code t
+if
+.meta value
+is a lazy cons cell. Otherwise
+it returns
+.codn nil ,
+even if
+.meta value
+is an ordinary cons cell.
+
+.coNP Function @ lcons-fun
+.synb
+.mets (lcons-fun << lazy-cons )
+.syne
+.desc
+The
+.code lcons-fun
+function retrieves the update function of a lazy cons.
Once a lazy cons has been accessed, it no longer has an update function
-and lcons-fun returns nil. While the update function of a lazy cons is
+and
+.code lcons-fun
+returns
+.codn nil .
+While the update function of a lazy cons is
executing, it is still accessible. This allows the update function
to retrieve a reference to itself and propagate itself into
-another lazy cons (as in the example under make-lazy-cons).
-
-.SS Functions lazy-stream-cons and get-lines
-
-.TP
-Syntax:
-
- (lazy-stream-cons <stream>)
- (get-lines <stream>)
-
-.TP
-Description:
-
-The lazy-stream-cons and get-lines functions are synonyms. Thus, the following
-description of lazy-stream-cons also applies to get-lines.
-
-The lazy-stream-cons returns a lazy cons which generates a lazy list based on
-reading lines of text from input stream <stream>, which form the elements of
-the list. The get-line function is called on demand to add elements to the
+another lazy cons (as in the example under
+.codn make-lazy-cons ).
+
+.coNP Functions @ lazy-stream-cons and @ get-lines
+.synb
+.mets (lazy-stream-cons << stream )
+.mets (get-lines << stream )
+.syne
+.desc
+The
+.code lazy-stream-cons
+and
+.code get-lines
+functions are synonyms. Thus, the following
+description of
+.code lazy-stream-cons
+also applies to
+.codn get-lines .
+
+The
+.code lazy-stream-cons
+returns a lazy cons which generates a lazy list based on
+reading lines of text from input stream
+.metn stream ,
+which form the elements of
+the list. The
+.code get-line
+function is called on demand to add elements to the
list.
-The lazy-stream-cons function itself makes the first call to get-line
-on the stream. If this returns nil, then the stream is closed and nil is
+The
+.code lazy-stream-cons
+function itself makes the first call to
+.code get-line
+on the stream. If this returns
+.codn nil ,
+then the stream is closed and
+.code nil
+is
returned. Otherwise, a lazy cons is returned whose update function will install
-that line into the car field of the lazy cons, and continue the lazy list
-by making another call to lazy-stream-cons, installing the result into the
-cdr field.
-
-the string returned by get-line, and whose cdr contains the lazy function.
-
-The lazy-stream-cons function inspects the real-time property of a stream
-as if by the real-time-stream-p function. This determines which of two
+that line into the
+.code car
+field of the lazy cons, and continue the lazy list
+by making another call to
+.codn lazy-stream-cons ,
+installing the result into the
+.code cdr
+field.
+
+.code lazy-stream-cons
+inspects the real-time property of a stream
+as if by the
+.code real-time-stream-p
+function. This determines which of two
styles of lazy list are returned. For an ordinary (non-real-time) stream,
the lazy list treats the end-of-file condition accurately: an empty
-file turns into the empty list nil, a one line file into a one-element
-list which contains that line and so on. This accuracy requries one
-line of lookahead which is not acceptable in real-time streams. For real-time
-streams, the lazy list will generate an extra nil item after the last
-line, and so an empty input source translates to the list (nil).
-
-.SS Macro delay
-
-.TP
-Syntax:
-
- (delay <expression>)
-
-.TP
-Description:
+file turns into the empty list
+.codn nil ,
+a one line file into a one-element
+list which contains that line and so on. This accuracy requires one
+line of lookahead which is not acceptable in real-time streams, and
+so a different type of lazy list is used, which generates an extra
+.code nil
+item after the last line. Under this type of lazy list, an empty input stream
+translates to the list
+.codn (nil) ;
+a one-line stream translates to
+.codn ("line" nil)
+and so forth.
+.coNP Macro @ delay
+.synb
+.mets (delay << expression )
+.syne
+.desc
The delay operator arranges for the delayed (or "lazy") evaluation of
-<expression>. This means that the expression is not evaluated immediately.
+.metn expression .
+This means that the expression is not evaluated immediately.
Rather, the delay expression produces a promise object.
-The promise object can later be passed to the force function (described
+The promise object can later be passed to the
+.code force
+function (described
later in this document). The force function will trigger the evaluation
of the expression and retrieve the value.
-The expression is evaluated in the original scope, no mater where
-the force takes place.
+The expression is evaluated in the original scope, no matter where
+the
+.code force
+takes place.
-The expression is evaluated at most once, by the first call to force.
-Additional calls to force only retrieve a cached value.
+The expression is evaluated at most once, by the first call to
+.codn force .
+Additional calls to
+.code force
+only retrieve a cached value.
-.TP
-Example:
+.TP* Example:
+.cblk
@(do
;; list is popped only once: the value is computed
;; just once when force is called on a given promise
@@ -9091,7 +14720,6 @@ Example:
(format t "item is ~s\en" (force promise))
(format t "*list* is ~s\en" *list*))
-
(defvar *list* '(1 2 3))
(get-it (delay (pop *list*))))
@@ -9102,159 +14730,275 @@ Example:
item is 1
item is 1
*list* is (2 3)
-
-.SS Function force
-
-.TP
-Syntax:
-
- (force <promise>)
-
-.TP
-Description:
-
-The force function accepts a promise object produced by the delay macro.
-The first time force is invoked <promise>, the promise expression
-is evaluated (in its original lexical environment, regardless of where
-in the program the force call takes place). The value of the expression is
-cached inside <promise> and returned, becoming the return value of the
-force function call. If the force function is invoked additional times on
+.cble
+
+.coNP Function @ force
+.synb
+.mets (force << promise )
+.syne
+.desc
+The
+.code force
+function accepts a promise object produced by the
+.code delay
+macro.
+The first time
+.code force
+is invoked, the
+.meta expression
+which was wrapped inside
+.meta promise
+by the
+.code delay
+macro is evaluated (in its original lexical environment, regardless of where in
+the program the
+.code force
+call takes place). The value of
+.meta expression
+is
+cached inside
+.meta promise
+and returned, becoming the return value of the
+.code force
+function call. If the
+.code force
+function is invoked additional times on
the same promise, the cached value is retrieved.
-.SH LAZY SEQUENCES, RANGES, PERMUTATIONS AND COMBINATIONS
-
-.SS Functions generate and giterate
-
-.TP
-Syntax:
-
- (generate <while-fun> <gen-fun>)
- (giterate <while-fun> <gen-fun> [<value>])
-
-.TP
-Description:
-
-The generate function produces a lazy list which dynamically produces items
+.SS* Lazy Sequences, Ranges, Permutations and Combinations
+.coNP Functions @ generate and @ giterate
+.synb
+.mets (generate < while-fun << gen-fun )
+.mets (giterate < while-fun < gen-fun <> [ value ])
+.syne
+.desc
+The
+.code generate
+function produces a lazy list which dynamically produces items
according to the following logic.
-The arguments to generate are functions which do not take any arguments. The
+The arguments to
+.code generate
+are functions which do not take any arguments. The
return value of generate is a lazy list.
When the lazy list is accessed, for instance with the functions car and cdr, it
-produces items on demand. Prior to producing each item, <while-fun> is
-called. If it returns a true boolean value (any value other than nil), then
-the <gen-fun> function is called, and its return value is incorporated as
-the next item of the lazy list. But if <while-fun> yields nil, then the lazy
-list immediately terminates.
-
-Prior to returning the lazy list, generate invokes the <while-fun> one time.
-If while-fun yields nil, then generate returns the empty list nil instead
-of a lazy list. Otherwise, it instantiates a lazy list, and invokes
-the gen-func to populate it with the first item.
-
-The giterate function is similar to generate, except that <while-fun>
-and <gen-fun> are functions of one argument rather than functions of
-no arguments. The optional <value> argument defaults to nil and
-is threaded through the function calls. That is to say, the lazy
-list returned is (<value> [<gen-fun <value>] [<gen-fun> [<gen-fun> <value>]] ...).
-
-The lazy list terminates when a value fails to satsify <while-fun>.
+produces items on demand. Prior to producing each item,
+.meta while-fun
+is
+called. If it returns a true boolean value (any value other than
+.codn nil ),
+then
+the
+.meta gen-fun
+function is called, and its return value is incorporated as
+the next item of the lazy list. But if
+.meta while-fun
+yields
+.codn nil ,
+then the lazy list immediately terminates.
+
+Prior to returning the lazy list, generate invokes the
+.meta while-fun
+one time.
+If
+.code while-fun
+yields
+.codn nil ,
+then
+.code generate
+returns the empty list
+.code nil
+instead of a lazy list. Otherwise, it instantiates a lazy list, and invokes the
+.code gen-func
+to populate it with the first item.
+
+The
+.code giterate
+function is similar to
+.codn generate ,
+except that
+.meta while-fun
+and
+.meta gen-fun
+are functions of one argument rather than functions of
+no arguments. The optional
+.meta value
+argument defaults to
+.code nil
+and is threaded through the function calls. That is to say, the lazy
+list returned is
+.cblk
+.meti >> ( value >> [ gen-fun << value ] >> [ gen-fun >> [ gen-fun << value ]] ...).
+.cble
+
+The lazy list terminates when a value fails to satsify
+.metn while-fun .
That is to say, prior to generating each value, the lazy list tests
-the value using <while-fun>. If that function returns false, then
-the item is not added, and the sequence terminates.
+the value using
+.metn while-fun .
+If that function returns
+.codn nil ,
+then the item is not added, and the sequence terminates.
-Note: the giterate function could be written in terms of generate
+Note:
+.code giterate
+could be written in terms of
+.code generate
like this:
+.cblk
(defun giterate (w g v)
- (generate (lambda () [w v]) (lambda () (prog1 v (set v [g v])))))
+ (generate (lambda () [w v])
+ (lambda () (prog1 v (set v [g v])))))
+.cble
-.SS
-Example:
+.TP* Example:
+.cblk
(giterate (op > 5) (op + 1) 0) -> (0 1 2 3 4)
+.cble
-.SS Function repeat
-
-
-Syntax:
-
- (repeat <list> [<count>])
-
-.TP
-Description:
-
-If <list> is empty, then repeat returns an empty list.
+.coNP Function @ repeat
+.synb
+.mets (repeat < list <> [ count ])
+.syne
+.desc
+If
+.meta list
+is empty, then repeat returns an empty list.
-If <count> is omitted, the repeat function produces an infinite lazy list
-formed by catenating together copies of <list>.
+If
+.meta count
+is omitted, the
+.code repeat
+function produces an infinite lazy list
+formed by catenating together copies of
+.metn list .
-If <count> is specified and is zero or negative, then an empty list is
+If
+.meta count
+is specified and is zero or negative, then an empty list is
returned.
-Otherwise a list is returned consisting of <count> repetitions of <list>
+Otherwise a list is returned consisting of
+.meta count
+repetitions of
+.meta list
catenated together.
-.SS Macros gen and gun
-
-.TP
-Syntax:
-
- (gen <while-expression> <produce-item-expression>)
- (gun <produce-item-expression>)
-
-.TP
-Description:
-
-The gen macro operator produces a lazy list, in a manner similar to the
-generate function. Whereas the generate function takes functional arguments,
-the gen operator takes two expressions, which is often more convenient.
-
-The return value of gen is a lazy list. When the lazy list is accessed, for
-instance with the functions car and cdr, it produces items on demand. Prior to
-producing each item, the <while-expression> is evaluated, in its original
-lexical scope. If the expression yields a true value (non-nil), then
-<produce-item-expression> is evaluated, and its return value is incorporated as
-the next item of the lazy list. If the expression yields nil, then the lazy
-list immediately terminates.
-
-The gen operator itself immediately evaluates <while-expression> before
-producing the lazy list. If the expression yields nil, then the operator
-returns the empty list nil. Otherwise, it instantiates the lazy list and
-invokes the <produce-item-expression> to force the first item.
-
-The gun macro similarly creates a lazy list according to the following
+.coNP Macros @ gen and @ gun
+.synb
+.mets (gen < while-expression << produce-item-expression )
+.mets (gun << produce-item-expression )
+.syne
+.desc
+The
+.code gen
+macro operator produces a lazy list, in a manner similar to the
+.code generate
+function. Whereas the
+.code generate
+function takes functional arguments,
+the
+.code gen
+operator takes two expressions, which is often more convenient.
+
+The return value of
+.code gen
+is a lazy list. When the lazy list is accessed, for
+instance with the functions
+.code car
+and
+.codn cdr ,
+it produces items on demand. Prior to
+producing each item, the
+.meta while-expression
+is evaluated, in its original
+lexical scope. If the expression yields a
+.cod2 non- nil
+value, then
+.meta produce-item-expression
+is evaluated, and its return value is incorporated as
+the next item of the lazy list. If the expression yields
+.codn nil ,
+then the lazy list immediately terminates.
+
+The
+.code gen
+operator itself immediately evaluates
+.meta while-expression
+before
+producing the lazy list. If the expression yields
+.codn nil ,
+then the operator
+returns the empty list
+.codn nil .
+Otherwise, it instantiates the lazy list and
+invokes the
+.meta produce-item-expression
+to force the first item.
+
+The
+.code gun
+macro similarly creates a lazy list according to the following
rules. Each successive item of the lazy list is obtained as a result of
-evaluating <produce-item-expression>. However, when <produce-item-expression>
-yields nil, then the list terminates (without adding that nil as an item).
-
-Note 1: the form gun can be implemented as a macro-expanding to
-an instance of the gen operator, like this:
-
+evaluating
+.metn produce-item-expression .
+However, when
+.meta produce-item-expression
+yields
+.codn nil ,
+then the list terminates (without adding that
+.code nil
+as an item).
+
+Note 1: the form
+.code gun
+can be implemented as a macro-expanding to
+an instance of the
+.code gen
+operator, like this:
+
+.cblk
(defmacro gun (expr)
(let ((var (gensym)))
^(let (,var)
(gen (set ,var ,expr)
,var))))
+.cble
-This exploits the fact that the set operator returns the value that is
-assigned, so the set expression is tested as a condition by gen,
+This exploits the fact that the
+.code set
+operator returns the value that is
+assigned, so the set expression is tested as a condition by
+.codn gen ,
while having the side effect of storing the next item temporarily
in a hidden variable.
-In turn, gen can be implemented as a macro expanding to some lambda
-functions which are passed to the generate function:
+In turn,
+.code gen
+can be implemented as a macro expanding to some
+.code lambda
+functions which are passed to the
+.code generate
+function:
+.cblk
(defmacro gen (while-expr produce-expr)
^(generate (lambda () ,while-expr) (lambda () ,produce-expr)))
+.cble
-Note 2: GEN can be considered as an acronym for Generate, testing Expression
-before Next item, whereas GUN stands for Generate Until Null.
-
-.TP
+Note 2:
+.code gen
+can be considered as an acronym for Generate, testing Expression
+before Next item, whereas
+.code gun
+stands for Generate Until Null.
-Example:
+.TP* Example:
+.cblk
@(do
;; Make a lazy list of integers up to 1000
;; access and print the first three.
@@ -9264,769 +15008,996 @@ Example:
Output:
1 2 3
-
-.SS Functions range and range*
-
-.TP
-Syntax:
-
- (range [ [ [ <from> ] <to> ] <step> ])
- (range* [ [ [ <from> ] <to> ] <step> ])
-
-.TP
-Description:
-
-The range and range* functions generate a lazy sequence of integers, with a
+.cble
+
+.coNP Functions @ range and @ range*
+.synb
+.mets (range <> [[[ from ] << to ] << step ])
+.mets (range* <> [[[ from ] << to ] << step ])
+.syne
+.desc
+The
+.code range
+and
+.code range*
+functions generate a lazy sequence of integers, with a
fixed step between successive values.
-The difference between range and range* is that range* excludes the endpoint.
-For instance (range 0 3) generates the list (0 1 2 3), whereas (range* 0 3)
-generates (0 1 2).
-
-All arguments are optional. If the <step> argument is omitted, then it defaults
-to 1: each value in the sequence is greater than the previous one by 1.
+The difference between
+.code range
+and
+.code range*
+is that
+.code range*
+excludes the endpoint.
+For instance
+.code (range 0 3)
+generates the list
+.codn (0 1 2 3) ,
+whereas
+.code (range* 0 3)
+generates
+.codn (0 1 2) .
+
+All arguments are optional. If the
+.meta step
+argument is omitted, then it defaults
+to
+.codn 1 :
+each value in the sequence is greater than the previous one by
+.codn 1 .
Positive or negative step sizes are allowed. There is no check for a step size
of zero, or for a step direction which cannot meet the endpoint.
-The <to> argument specifies the endpoint value, which, if it occurs in the
-sequence, is excluded from it by the range* function, but included by the range
-function. If <to> is missing, or specified as nil, then there is no endpoint,
-and the sequence which is generated is infinite, regardless of <step>.
+The
+.meta to
+argument specifies the endpoint value, which, if it occurs in the
+sequence, is excluded from it by the
+.code range*
+function, but included by the range
+function. If
+.meta to
+is missing, or specified as
+.codn nil ,
+then there is no endpoint,
+and the sequence which is generated is infinite, regardless of
+.metn step .
-If <from> is omitted, then the sequence begins at zero, otherwise <from> must
-be an integer which specifies the initial value.
+If
+.meta from
+is omitted, then the sequence begins at zero, otherwise
+.meta from
+must be an integer which specifies the initial value.
The sequence stops if it reaches the endpoint value (which is included in the
-case of range, and excluded in the case of range*). However, a sequence with a
-stepsize greater than 1 or less than -1 might step over the endpoint value, and
+case of
+.codn range ,
+and excluded in the case of
+.codn range *).
+However, a sequence with a stepsize greater than
+.code 1
+or less than
+.code -1
+might step over the endpoint value, and
therefore never attain it. In this situation, the sequence also stops, and the
excess value which surpasses the endpoint is excluded from the sequence.
-.SS Function perm
-
-.TP
-Syntax:
-
- (perm <seq> [<len>])
+.coNP Function @ perm
+.synb
+.mets (perm < seq <> [ len ])
+.syne
+.desc
+The
+.code rperm
+function returns a lazy list which consists of all
+length
+.meta len
+permutations of formed by items taken from
+.metn seq .
+The permutations do not use any element of
+.meta seq
+more than once.
+
+Argument
+.metn len ,
+if present, must be a positive integer, and
+.meta seq
+must be a sequence.
-.TP
-Description:
-
-The rperm function returns a lazy list which consists of all
-length <len> permutations of formed by items taken from <seq>.
-The permutations do not use any element of <seq> more than once.
-
-Argument <len>, if present, must be a positive integer, and <seq> must be a
-sequence.
-
-If <len> is not present, then its value defaults to the length of <seq>:
+If
+.meta len
+is not present, then its value defaults to the length of
+.metn seq :
the list of the full permutations of the entire sequence is returned.
-The permutations in the returned list are sequences of the same kind as <seq>.
+The permutations in the returned list are sequences of the same kind as
+.codn seq .
-If <len> is zero, then a list containing one permutation is returned, and that
+If
+.meta len
+is zero, then a list containing one permutation is returned, and that
permutations is of zero length.
-If <len> exceeds the length of <seq>, then an empty list is returned,
+If
+.meta len
+exceeds the length of
+.metn seq ,
+then an empty list is returned,
since it is impossible to make a single non-repeating permutation that
requires more items than are available.
The permutations are lexicographically ordered.
-.SS Function rperm
-
-.TP
-Syntax:
-
- (rperm <seq> <len>)
-
-.TP
-Description:
-
-The rperm function returns a lazy list which consists of all the repeating
-permutations of length <len> formed by items taken from <seq>.
-"Repeating" means that the items from <seq> can appear more than
+.coNP Function @ rperm
+.synb
+.mets (rperm < seq << len )
+.syne
+.desc
+The
+.code rperm
+function returns a lazy list which consists of all the repeating
+permutations of length
+.meta len
+formed by items taken from
+.metn seq .
+"Repeating" means that the items from
+.meta seq
+can appear more than
once in the permutations.
-The permutations which are returned are sequences of the same kind as <seq>.
+The permutations which are returned are sequences of the same kind as
+.metn seq .
-Argument <len> must be a nonnegative integer, and <seq> must be a sequence.
+Argument
+.meta len
+must be a nonnegative integer, and
+.meta seq
+must be a sequence.
-If <len> is zero, then a single permutation is returned, of zero length.
-This is true regardless of whether <seq> is itself empty.
+If
+.meta len
+is zero, then a single permutation is returned, of zero length.
+This is true regardless of whether
+.meta seq
+is itself empty.
-If <seq> is empty and <len> is greater than zero, then no permutations are
+If
+.meta seq
+is empty and
+.meta len
+is greater than zero, then no permutations are
returned, since permutations of a positive length require items, and the
sequence has no items. Thus there exist no such permutations.
-The first permutation consists of <len> repetitions of the first element of
-<seq>. The next repetition, if there is one, differs from the first
-repetition in that its last element is the second element of <seq>.
+The first permutation consists of
+.meta le
+repetitions of the first element of
+.metn seq .
+The next repetition, if there is one, differs from the first
+repetition in that its last element is the second element of
+.metn seq .
That is to say, the permutations are lexicographically ordered.
-.TP
-Examples:
+.TP* Examples:
- (rperm "01" 4) -> ("000" "001" "010" "011" "100" "101" "110" "111")
+.cblk
+ (rperm "01" 4) -> ("000" "001" "010" "011"
+ "100" "101" "110" "111")
(rperm #(1) 3) -> (#(1 1 1))
- (rperm '(0 1 2) 2) -> ((0 0) (0 1) (0 2) (1 0) (1 1) (1 2) (2 0) (2 1) (2 2))
-
-
-.SS Function comb
-
-.TP
-Syntax:
-
- (comb <seq> <len>)
-
-.TP
-Description:
-
-The comb function returns a lazy list which consists of all
-length <len> non-repeating combinations formed by taking items taken from
-<seq>. "Non-repeating combinations" means that the combinations do not use any
-element of <seq> more than once. If <seq> contains no duplicates, then
+ (rperm '(0 1 2) 2) -> ((0 0) (0 1) (0 2) (1 0)
+ (1 1) (1 2) (2 0) (2 1) (2 2))
+.cble
+
+.coNP Function @ comb
+.synb
+.mets (comb < seq << len )
+.syne
+.desc
+The
+.code comb
+function returns a lazy list which consists of all
+length
+.meta len
+non-repeating combinations formed by taking items taken from
+.metn seq .
+"Non-repeating combinations" means that the combinations do not use any
+element of
+.meta seq
+more than once. If
+.meta seq
+contains no duplicates, then
the combinations contain no duplicates.
-Argument <len> must be a nonnegative integer, and <seq> must be a sequence
-or a hash table.
+Argument
+.meta len
+must be a nonnegative integer, and
+.meta seq
+must be a sequence or a hash table.
-The combinations in the returned list are objects of the same kind as <seq>.
+The combinations in the returned list are objects of the same kind as
+.metn seq .
-If <len> is zero, then a list containing one combination is returned, and that
+If
+.meta len
+is zero, then a list containing one combination is returned, and that
permutations is of zero length.
-If <len> exceeds the number of elements in <seq>, then an empty list is
-returned, since it is impossible to make a single non-repeating combination
-that requires more items than are available.
-
-If <seq> is a sequence, the returned combinations are lexicographically ordered.
-This requirement is not applicable when <seq> is a hash table.
-
-.SS Function rcomb
-
-.TP
-Syntax:
-
- (rcomb <seq> <len>)
-
-.TP
-Description:
-
-The comb function returns a lazy list which consists of all
-length <len> repeating combinations formed by taking items taken from
-<seq>. "Repeating combinations" means that the combinations can use
-an element of <seq> more than once.
-
-Argument <len> must be a nonnegative integer, and <seq> must be a sequence.
+If
+.meta len
+exceeds the number of elements in
+.metn seq ,
+then an empty list is returned, since it is impossible to make a single
+non-repeating combination that requires more items than are available.
-The combinations in the returned list are sequences of the same kind as <seq>.
+If
+.meta seq
+is a sequence, the returned combinations are lexicographically ordered.
+This requirement is not applicable when
+.meta seq
+is a hash table.
+
+.coNP Function @ rcomb
+.synb
+.mets (rcomb < seq << len )
+.syne
+.desc
+The
+.code comb
+function returns a lazy list which consists of all
+length
+.meta len
+repeating combinations formed by taking items taken from
+.metn seq .
+"Repeating combinations" means that the combinations can use
+an element of
+.meta seq
+more than once.
+
+Argument
+.meta len
+must be a nonnegative integer, and
+.meta seq
+must be a sequence.
+
+The combinations in the returned list are sequences of the same kind as
+.metn seq .
-If <len> is zero, then a list containing one combination is returned, and that
-permutations is of zero length. This is true even if <seq> is empty.
+If
+.meta len
+is zero, then a list containing one combination is returned, and that
+permutations is of zero length. This is true even if
+.meta seq
+is empty.
-If <seq> is empty, and <len> is nonzero, then an empty list is returned.
+If
+.meta seq
+is empty, and
+.meta len
+is nonzero, then an empty list is returned.
The combinations are lexicographically ordered.
-.SH CHARACTERS AND STRINGS
-
-.SS Function mkstring
-
-.TP
-Syntax:
-
- (mkstring <length> <char>)
-
-.TP
-Description:
-
-The mkstring function constructs a string object of a length specified
-by the <length> parameter. Every position in the string is initialized
-with <char>, which must be a character value.
-
-.SS Function copy-str
-
-.TP
-Syntax:
-
- (copy-str <string>)
-
-.TP
-Description:
-
-The copy-str function constructs a new string whose contents are identical
-to <string>.
-
-.SS Function upcase-str
-
-.TP
-Syntax:
-
- (upcase-str <string>)
-
-.TP
-Description:
-
-The upcase-str function produces a copy of <string> such that all lower-case
+.SS* Characters and Strings
+.coNP Function @ mkstring
+.synb
+.mets (mkstring < length << char )
+.syne
+.desc
+The
+.code mkstring
+function constructs a string object of a length specified
+by the
+.meta length
+parameter. Every position in the string is initialized
+with
+.metn char ,
+which must be a character value.
+
+.coNP Function @ copy-str
+.synb
+.mets (copy-str << string )
+.syne
+.desc
+The
+.code copy-str
+function constructs a new string whose contents are identical
+to
+.metn string .
+
+.coNP Function @ upcase-str
+.synb
+.mets (upcase-str << string )
+.syne
+.desc
+The
+.code upcase-str
+function produces a copy of
+.meta string
+such that all lower-case
characters of the English alphabet are mapped to their upper case counterparts.
-.SS Function downcase-str
-
-.TP
-Syntax:
-
- (downcase-str <string>)
-
-.TP
-Description:
-
-The downcase-str function produces a copy of <string> such that
+.coNP Function @ downcase-str
+.synb
+.mets (downcase-str << string )
+.syne
+.desc
+The
+.code downcase-str
+function produces a copy of
+.meta string
+such that
all upper case characters of the English alphabet are mapped to their
lower case counterparts.
-.SS Function string-extend
-
-.TP
-Syntax:
-
- (string-extend <string> <tail>)
-
-.TP
-Description:
-
-The string-extend function destructively increases the length of <string>,
+.coNP Function @ string-extend
+.synb
+.mets (string-extend < string << tail )
+.syne
+.desc
+The
+.code string-extend
+function destructively increases the length of
+.metn string ,
which must be an ordinary dynamic string. It is an error to invoke this
function on a literal string or a lazy string.
-The <tail> argument can be a character, string or integer. If it is a string or
+The
+.meta tail
+argument can be a character, string or integer. If it is a string or
character, it specifies material which is to be added to the end of the string:
either a single character or a sequence of characters. If it is an integer, it
specifies the number of characters to be added to the string.
-If <tail> is an integer, the newly added characters have indeterminate contents.
+If
+.meta tail
+is an integer, the newly added characters have indeterminate contents.
The string appears to be the original one because of an internal terminating
null character remains in place, but the characters beyond the terminating zero
are indeterminate.
-.SS Function stringp
-
-.TP
-Syntax:
-
- (stringp <obj>)
-
-.TP
-Description:
-
-The stringp function returns t if <obj> is one of the several
-kinds of strings. Otherwise it returns nil.
-
-.SS Function length-str
-
-.TP
-Syntax:
-
- (length-str <string>)
-
-.TP
-Description:
-
-The length-str function returns the length <string> in characters.
-The argument must be a string.
-
-.SS Function search-str
-
-.TP
-Syntax:
-
- (search-str <haystack> <needle> [<start> [<from-end>]])
-
-.TP
-Description:
-
-The search-str function finds an occurrence of the string <needle> inside
-the <haystack> string and returns its position. If no such occurrence exists,
-it returns nil.
-
-If a <start> argument is not specified, it defaults to zero. If it is
+.coNP Function @ stringp
+.synb
+.mets (stringp << obj )
+.syne
+.desc
+The
+.code stringp
+function returns t if
+.meta obj
+is one of the several
+kinds of strings. Otherwise it returns
+.codn nil .
+
+.coNP Function @ length-str
+.synb
+.mets (length-str << string )
+.syne
+.desc
+The
+.code length-str
+function returns the length
+.meta string
+in characters. The argument must be a string.
+
+.coNP Function @ search-str
+.synb
+.mets (search-str < haystack < needle >> [ start <> [ from-end ]])
+.syne
+.desc
+The
+.code search-str
+function finds an occurrence of the string
+.meta needle
+inside
+the
+.meta haystack
+string and returns its position. If no such occurrence exists,
+it returns
+.codn nil .
+
+If a
+.meta start
+argument is not specified, it defaults to zero. If it is
a non-negative integer, it specifies the starting character position for
-the search. Negative values of <start> indicate positions from the end of the
-string, such that -1 is the last character of the string.
-
-If the <from-end> argument is specified and is not nil, it means
+the search. Negative values of
+.meta start
+indicate positions from the end of the
+string, such that
+.code -1
+is the last character of the string.
+
+If the
+.meta from-end
+argument is specified and is not
+.codn nil ,
+it means
that the search is conducted right-to-left. If multiple matches are possible,
it will find the rightmost one rather than the leftmost one.
-.SS Function search-str-tree
-
-.TP
-Syntax:
-
- (search-str-tree <haystack> <tree> [<start> [<from-end>]])
-
-.TP
-Description:
-
-The search-str-tree function is similar to search-str, except that instead of
-searching <haystack> for the occurrence of a single needle string, it searches
+.coNP Function @ search-str-tree
+.synb
+.mets (search-str-tree < haystack < tree >> [ start <> [ from-end ]])
+.syne
+.desc
+The
+.code search-str-tree
+function is similar to
+.codn search-str ,
+except that instead of
+searching
+.meta haystack
+for the occurrence of a single needle string, it searches
for the occurrence of numerous strings at the same time. These search strings
-are specified, via the <tree> argument, as an arbitrarily structured tree whose
+are specified, via the
+.meta tree
+argument, as an arbitrarily structured tree whose
leaves are strings.
The function finds the earliest possible match, in the given search direction,
from among all of the needle strings.
-If <tree> is a single string, the semantics is equivalent to
-search-str.
-
-.SS Function match-str
-
-.TP
-Syntax:
-
- (match-str <bigstring> <littlestring> [<start>])
-
-.TP
-Description:
-
-Without the <start> argument, the match-str function determines whether
-<littlestring> is a prefix of <bigstring>, returning a t or nil
+If
+.meta tree
+is a single string, the semantics is equivalent to
+.codn search-str .
+
+.coNP Function @ match-str
+.synb
+.mets (match-str < bigstring < littlestring <> [ start ])
+.syne
+.desc
+Without the
+.meta start
+argument, the
+.code match-str
+function determines whether
+.meta littlestring
+is a prefix of
+.metn bigstring ,
+returning a
+.code t
+or
+.code nil
indication.
-If the <start> argument is specified, and is a non-negative integer, then the
-function tests whether <littlestring> matches a prefix of that portion of
-<bigstring> which starts at the given position.
-
-If the <start> argument is a negative integer, then match-str determines
-whether <littlestring> is a suffix of <bigstring>, ending on that position
-of bigstring, where -1 denotes the last character of <bigstring>,
--2 the second last one and so on.
-
-If <start> is -1, then this corresponds to testing whether <littlestring>
-is a suffix of <bigstring>.
-
-.SS Function match-str-tree
+If the
+.meta start
+argument is specified, and is a non-negative integer, then the
+function tests whether
+.meta littlestring
+matches a prefix of that portion of
+.meta bigstring
+which starts at the given position.
+
+If the
+.meta start
+argument is a negative integer, then
+.code match-str
+determines
+whether
+.meta littlestring
+is a suffix of
+.metn bigstring ,
+ending on that position
+of bigstring, where
+.code -1
+denotes the last character of
+.metn bigstring ,
+.code -2
+the second last one and so on.
-.TP
-Syntax:
-
- (match-str-tree <bigstring> <tree> [<start>])
-
-.TP
-Description:
-
-The match-str-tree function is a generalization of match-str which matches
-multiple test strings against <bigstring> at the same time. The value
+If
+.meta start
+is
+.codn -1 ,
+then this corresponds to testing whether
+.meta littlestring
+is a suffix of
+.metn bigstring .
+
+.coNP Function @ match-str-tree
+.synb
+.mets (match-str-tree < bigstring < tree <> [ start ])
+.syne
+.desc
+The
+.code match-str-tree
+function is a generalization of match-str which matches
+multiple test strings against
+.meta bigstring
+at the same time. The value
reported is the longest match from among any of the strings.
The strings are specified as an arbitrarily shaped tree structure which has
strings at the leaves.
-If <tree> is a single string atom, then the function behaves
+If
+.meta tree
+is a single string atom, then the function behaves
exactly like match-str.
-.SS Function sub-str
-
-.TP
-Syntax:
-
- (sub-str <string> [<from> [<to>]])
-
-.TP
-Description:
-
-The sub-str function is like the more generic function sub, except that it
+.coNP Function @ sub-str
+.synb
+.mets (sub-str < string >> [ from <> [ to ]])
+.syne
+.desc
+The
+.code sub-str
+function is like the more generic function
+.codn sub ,
+except that it
operates only on strings. For a description of the arguments and semantics,
-refer to the sub function.
-
-.SS Function replace-str
-
-.TP
-Syntax:
-
- (replace-str <string> <item-sequence> [<from> [<to>]])
-
-.TP
-Description:
+refer to the
+.code sub
+function.
-The replace-str function is like the replace function, except that the first
+.coNP Function @ replace-str
+.synb
+.mets (replace-str < string < item-sequence >> [ from <> [ to ]])
+.syne
+.desc
+The
+.code replace-str
+function is like the
+.code replace
+function, except that the first
argument must be a string.
-For a description of the arguments and semantics, refer to the replace function.
-
-.SS Function cat-str
-
-.TP
-Syntax:
-
- (cat-str <string-list> [<sep-string>])
-
-.TP
-Description:
+For a description of the arguments and semantics, refer to the
+.code replace
+function.
-The cat-str function catenates a list of strings given by <string-list> into a
-single string. The optional <sep-string> argument specifies a separator string
+.coNP Function @ cat-str
+.synb
+.mets (cat-str < string-list <> [ sep-string ])
+.syne
+.desc
+The
+.code cat-str
+function catenates a list of strings given by
+.meta string-list
+into a
+single string. The optional
+.meta sep-string
+argument specifies a separator string
which is interposed between the catenated strings.
-.SS Function split-str
-
-.TP
-Syntax:
-
- (split-str <string> <sep>)
-
-.TP
-Description:
-
-The split-str function breaks the <string> into pieces, returning a list
-thereof. The <sep> argument must be either a string or a regular expression.
-It specifies the separator character sequence within <string>.
-
-All non-overlapping matches for <sep> within <string> are identified in left
-to right order, and are removed from <string>. The string is broken into pieces
+.coNP Function @ split-str
+.synb
+.mets (split-str < string << sep )
+.syne
+.desc
+The
+.code split-str
+function breaks the
+.meta string
+into pieces, returning a list
+thereof. The
+.meta sep
+argument must be either a string or a regular expression.
+It specifies the separator character sequence within
+.metn string .
+
+All non-overlapping matches for
+.meta sep
+within
+.meta string
+are identified in left
+to right order, and are removed from
+.metn string .
+The string is broken into pieces
according to the gaps left behind by the removed separators, and a list
of the remaining pieces is returned.
-If a match for <sep> is not found in the string at all, then the string is not
+If a match for
+.meta sep
+is not found in the string at all, then the string is not
split at all: a list of one element is returned containing the original
string.
-If <sep> matches the entire string, then a list of two empty strings is
+If
+.meta sep
+matches the entire string, then a list of two empty strings is
returned, except in the case that the original string is empty, in which case a
list of one element is returned, containing the empty string.
-Whenever two adjacent matches for <sep> occur, they are considered separate
+Whenever two adjacent matches for
+.meta sep
+occur, they are considered separate
cuts with an empty piece between them.
-This operation is nondestructive: <string> is not modified in any way.
-
-.SS Function split-str-set
-
-.TP
-Syntax:
-
- (split-str-set <string> <set>)
-
-.TP
-Description:
-
-The split-str-set function breaks the <string> into pieces, returning a list
-thereof. The <sep> argument must be a string. It specifies a set of
-characters. All occurrences of any of these characters within <string> are
-identified, and are removed from <string>. The string is broken into pieces
+This operation is nondestructive:
+.meta string
+is not modified in any way.
+
+.coNP Function @ split-str-set
+.synb
+.mets (split-str-set < string << set )
+.syne
+.desc
+The
+.code split-str-set
+function breaks the
+.meta string
+into pieces, returning a list
+thereof. The
+.meta sep
+argument must be a string. It specifies a set of
+characters. All occurrences of any of these characters within
+.meta string
+are
+identified, and are removed from
+.metn string .
+The string is broken into pieces
according to the gaps left behind by the removed separators.
-Adjacent occurrences of characters from <set> within <string> are considered to
+Adjacent occurrences of characters from
+.meta set
+within
+.meta string
+are considered to
be separate gaps which come between empty strings.
-This operation is nondestructive: <string> is not modified in any way.
-
-.SS Functions tok-str and tok-where
-
-.TP
-Syntax:
-
- (tok-str <string> <regex> [<keep-between>])
- (tok-where <string> <regex>)
-
-.TP
-Description:
-
-The tok-str function searches <string> for tokens, which are defined as
-substrings of <string> which match the regular expression <regex> in the
-longest possible way, and do not overlap. These tokens are extracted from the
+This operation is nondestructive:
+.meta string
+is not modified in any way.
+
+.coNP Functions @ tok-str and @ tok-where
+.synb
+.mets (tok-str < string < regex <> [ keep-between ])
+.mets (tok-where < string << regex )
+.syne
+.desc
+The
+.code tok-str
+function searches
+.meta string
+for tokens, which are defined as
+substrings of
+.mta string
+which match the regular expression
+.meta regex
+in the
+longest possible way, and do not overlap. These tokens are extracted from the
string and returned as a list.
-Whenever <regex> matches an empty string, then an empty token is returned, and
-the search for another token within <string> resumes after advancing by one
-character position. So for instance, (tok-str "abc" #/a?/) returns the
-list ("a" "" "" ""). After the token "a" is extracted from a non-empty match
+Whenever
+.meta regex
+matches an empty string, then an empty token is returned, and
+the search for another token within
+.meta string
+resumes after advancing by one
+character position. So for instance,
+.code (tok-str "abc" #/a?/)
+returns the
+.cblk
+("a" "" "" "").
+.cble
+After the token
+.str "a"
+is extracted from a non-empty match
for the regex, the regex is considered to match three more times: before the
-"b", between "b" and "c", and after the "c".
-
-If the <keep-between> argument is specified, and is not nil, then the behavior
-of tok-str changes in the following way. The pieces of <string> which are
+.strn "b" ,
+between
+.str "b"
+and
+.strn "c" ,
+and after the
+.strn "c" .
+
+If the
+.meta keep-betwee
+argument is specified, and is not
+.codn nil ,
+then the behavior
+of
+.code tok-str
+changes in the following way. The pieces of
+.meta string
+which are
skipped by the search for tokens are included in the output. If no token is
-found in <string>, then a list of one element is returned, containing <string>.
+found in
+.metn string ,
+then a list of one element is returned, containing
+.metn string .
Generally, if N tokens are found, then the returned list consists of 2N + 1
elements. The first element of the list is the (possibly empty) substring which
had to be skipped to find the first token. Then the token follows. The next
element is the next skipped substring and so on. The last element is the
-substring of <string> between the last token and the end.
-
-The tok-where function works similarly to tok-str, but instead of returning
+substring of
+.meta string
+between the last token and the end.
+
+The
+.code tok-where
+function works similarly to
+.codn tok-str ,
+but instead of returning
the extracted tokens themselves, it returns a list of the character position
-ranges within <string> where matches for <regex> occur. The ranges
+ranges within
+.meta string
+where matches for
+.meta regex
+occur. The ranges
are pairs of numbers, represented as cons cells, where the first number
of the pair gives the starting character position, and the second number
is one position past the end of the match. If a match is empty, then the
two numbers are equal.
-The tok-where function does not support the <keep-between> parameter.
-
-.SS Function list-str
-
-.TP
-Syntax:
-
- (list-str <string>)
-
-.TP
-Description:
-
-The list-str function converts a string into a list of characters.
-
-.SS Function trim-str
-
-.TP
-Syntax:
-
- (trim-str <string>)
-
-.TP
-Description:
-
-The trim-str function produces a copy of <string> from which leading and
+The tok-where function does not support the
+.meta keep-between
+parameter.
+
+.coNP Function @ list-str
+.synb
+.mets (list-str << string )
+.syne
+.desc
+The
+.code list-str
+function converts a string into a list of characters.
+
+.coNP Function @ trim-str
+.synb
+.mets (trim-str << string )
+.syne
+.desc
+The
+.code trim-str
+function produces a copy of
+.meta string
+from which leading and
trailing whitespace is removed. Whitespace consists of spaces, tabs,
carriage returns, linefeeds, vertical tabs and form feeds.
-.SS Function chrp
-
-.TP
-Syntax:
-
- (chrp <obj>)
-
-.TP
-Description:
-
-Returns t if <obj> is a character, otherwise nil.
-
-.SS Function chr-isalnum
-
-.TP
-Syntax:
-
- (chr-isalnum <char>)
-
-.TP
-Description:
-
-Returns t if <char> is an alpha-numeric character, otherwise nil. Alpha-numeric
+.coNP Function @ chrp
+.synb
+.mets (chrp << obj )
+.syne
+.desc
+Returns
+.code t
+if
+.meta obj
+is a character, otherwise nil.
+
+.coNP Function @ chr-isalnum
+.synb
+.mets (chr-isalnum << char )
+.syne
+.desc
+Returns
+.code t
+if
+.meta char
+is an alpha-numeric character, otherwise nil. Alpha-numeric
means one of the upper or lower case letters of the English alphabet found in
ASCII, or an ASCII digit. This function is not affected by locale.
-.SS Function chr-isalpha
-
-.TP
-Syntax:
-
- (chr-isalpha <char>)
-
-.TP
-Description:
-
-Returns t if <char> is an alphabetic character, otherwise nil. Alphabetic
+.coNP Function @ chr-isalpha
+.synb
+.mets (chr-isalpha << char )
+.syne
+.desc
+Returns
+.code t
+if
+.meta char
+is an alphabetic character, otherwise
+.codn nil .
+Alphabetic
means one of the upper or lower case letters of the English alphabet found in
ASCII. This function is not affected by locale.
-.SS Function chr-isascii
-
-.TP
-Syntax:
-
- (chr-isalpha <char>)
-
-.TP
-Description:
-
-This function returns t if the code of character <char> is in the range
-0 to 127, inclusive. For characters outside of this range, it returns nil.
-
-.SS Function chr-iscntrl
-
-.TP
-Syntax:
-
- (chr-iscntrl <char>)
-
-.TP
-Description:
-
-This function returns t if the character <char> is a character whose code
+.coNP Function @ chr-isascii
+.synb
+.mets (chr-isalpha << char )
+.syne
+.desc
+This function returns
+.code t
+if the code of character
+.meta char
+is in the range 0 to 127 inclusive. For characters outside of this range, it
+returns
+.codn nil .
+
+.coNP Function @ chr-iscntrl
+.synb
+.mets (chr-iscntrl << char )
+.syne
+.desc
+This function returns
+.code t
+if the character
+.meta char
+is a character whose code
ranges from 0 to 31, or is 127. In other words, any non-printable ASCII
-character. For other characters, it returns nil.
-
-.SS Function chr-isdigit
-
-.TP
-Syntax:
-
- (chr-isdigit <char>)
-
-.TP
-Description:
-
-This function returns t if the character <char> is is an ASCII digit.
-Otherwise, it returns nil.
-
-.SS Function chr-isgraph
-
-.TP
-Syntax:
-
- (chr-isgraph <char>)
-
-.TP
-Description:
-
-This function returns t if <char> is a non-space printable ASCII character.
+character. For other characters, it returns
+.codn nil .
+
+.coNP Function @ chr-isdigit
+.synb
+.mets (chr-isdigit << char )
+.syne
+.desc
+This function returns
+.code t
+if the character
+.meta char
+is is an ASCII digit.
+Otherwise, it returns
+.codn nil .
+
+.coNP Function @ chr-isgraph
+.synb
+.mets (chr-isgraph << char )
+.syne
+.desc
+This function returns
+.code t
+if
+.meta char
+is a non-space printable ASCII character.
It returns nil if it is a space or control character.
It also returns nil for non-ASCII characters: Unicode characters with a code
above 127.
-.SS Function chr-islower
-
-.TP
-Syntax:
-
- (chr-islower <char>)
-
-.TP
-Description:
-
-This function returns t if <char> is an ASCII lower case letter. Otherwise it returns nil.
-
-.SS Function chr-isprint
-
-.TP
-Syntax:
-
- (chr-isprint <char>)
-
-.TP
-Description:
-
-This function returns t if <char> is an ASCII character which is not a
-control character. It also returns nil for all non-ASCII characters: Unicode
+.coNP Function @ chr-islower
+.synb
+.mets (chr-islower << char )
+.syne
+.desc
+This function returns
+.code t
+if
+.meta char
+is an ASCII lower case letter. Otherwise it returns
+.codn nil .
+
+.coNP Function @ chr-isprint
+.synb
+.mets (chr-isprint << char )
+.syne
+.desc
+This function returns
+.code t
+if
+.meta char
+is an ASCII character which is not a
+control character. It also returns
+.code nil
+for all non-ASCII characters: Unicode
characters with a code above 127.
-.SS Function chr-ispunct
-
-.TP
-Syntax:
-
- (chr-ispunct <char>)
-
-.TP
-Description:
-
-This function returns t if <char> is an ASCII character which is not a
+.coNP Function @ chr-ispunct
+.synb
+.mets (chr-ispunct << char )
+.syne
+.desc
+This function returns
+.code t
+if
+.meta char
+is an ASCII character which is not a
control character. It also returns nil for all non-ASCII characters: Unicode
characters with a code above 127.
-.SS Function chr-isspace
-
-.TP
-Syntax:
-
- (chr-isspace <char>)
-
-.TP
-Description:
-
-This function returns t if <char> is an ASCII whitespace character: any of the
-characters in the set #\espace, #\etab, #\elinefeed, #\enewline, #\ereturn,
-#\evtab, and #\epage. For all other characters, it returns nil.
-
-.SS Function chr-isupper
-
-.TP
-Syntax:
-
- (chr-isupper <char>)
-
-.TP
-Description:
-
-This function returns t if <char> is an ASCII upper case letter. Otherwise it returns nil.
-
-.SS Function chr-isxdigit
-
-.TP
-Syntax:
-
- (chr-isxdigit <char>)
-
-.TP
-Description:
-
-This function returns t if <char> is a hexadecimal digit. One of the ASCII
-letters A through F, or their lower-case equivalents, or an ASCII digit 0
-through 9.
-
-.SS Function chr-toupper
-
-.TP
-Syntax:
-
- (chr-toupper <char>)
-
-.TP
-Description:
-
-If character <char> is a lower case ASCII letter character, this function
+.coNP Function @ chr-isspace
+.synb
+.mets (chr-isspace << char )
+.syne
+.desc
+This function returns
+.code t
+if
+.meta char
+is an ASCII whitespace character: any of the
+characters in the set
+.codn #\espace ,
+.codn #\etab ,
+.codn #\elinefeed ,
+.codn #\enewline ,
+.codn #\ereturn ,
+.code #\evtab
+and
+.codn #\epage .
+For all other characters, it returns
+.codn nil .
+
+.coNP Function @ chr-isupper
+.synb
+.mets (chr-isupper < char )
+.syne
+.desc
+This function returns
+.code t
+if
+.meta char
+is an ASCII upper case letter. Otherwise it returns
+.codn nil .
+
+.coNP Function @ chr-isxdigit
+.synb
+.mets (chr-isxdigit << char )
+.syne
+.desc
+This function returns
+.code t
+if
+.meta char
+is a hexadecimal digit. One of the ASCII
+letters
+.code A
+through
+.codn F ,
+or their lower-case equivalents, or an ASCII digit
+.code 0
+through
+.codn 9 .
+
+.coNP Function @ chr-toupper
+.synb
+.mets (chr-toupper << char )
+.syne
+.desc
+If character
+.meta char
+is a lower case ASCII letter character, this function
returns the upper case equivalent character. If it is some other
-character, then it just returns <char>.
-
-.SS Function chr-tolower
-
-.TP
-Syntax:
-
- (chr-tolower <char>)
-
-.TP
-Description:
-
-If character <char> is an upper case ASCII letter character, this function
+character, then it just returns
+.metn char .
+
+.coNP Function @ chr-tolower
+.synb
+.mets (chr-tolower << char )
+.syne
+.desc
+If character
+.meta char
+is an upper case ASCII letter character, this function
returns the lower case equivalent character. If it is some other
-character, then it just returns <char>.
-
-.SS Functions num-chr and chr-num
-
-.TP
-Syntax:
-
- (num-chr <char>)
- (chr-num <num>)
-
-.TP
-Description:
-
-The argument <char> must be a character. The num-chr function returns that
+character, then it just returns
+.metn char .
+
+.coNP Functions @ num-chr and @ chr-num
+.synb
+.mets (num-chr << char )
+.mets (chr-num << num )
+.syne
+.desc
+The argument
+.meta char
+must be a character. The
+.code num-chr
+function returns that
character's Unicode code point value as an integer.
-The argument <num> must be a fixnum integer in the range 0 to #\e10FFFF.
+The argument
+.meta num
+must be a fixnum integer in the range
+.code 0
+to
+.codn #\ex10FFFF .
The argument is taken to be a Unicode code point value and the
corresponding character object is returned.
-.SS Function chr-str
-
-.TP
-Syntax:
-
- (chr-str <str> <idx>)
-
-.TP
-Description:
-
-The chr-str function performs random access on string <str> to retrieve
-the character whose position is given by integer <idx>, which must
+.coNP Function @ chr-str
+.synb
+.mets (chr-str < str << idx )
+.syne
+.desc
+The
+.code chr-str
+function performs random access on string
+.meta str
+to retrieve
+the character whose position is given by integer
+.metn idx ,
+which must
be within range of the string.
The index value 0 corresponds to the first (leftmost) character of the string
@@ -10040,93 +16011,122 @@ An empty string cannot be indexed. A string of length one supports index 0 and
index -1. A string of length two is indexed left to right by the values 0 and
1, and from right to left by -1 and -2.
-.TP
-Notes:
+.TP* Notes:
-Direct use of chr-str is equivalent to the DWIM bracket notation except
-that <str> must be a string. The following relation holds:
+Direct use of
+.code chr-str
+is equivalent to the DWIM bracket notation except
+that
+.code str
+must be a string. The following relation holds:
+.cblk
(chr-str s i) --> [s i]
+.cble
-since [s i] <--> (ref s i), this also holds:
+since
+.codn [s i] <--> (ref s i) ,
+this also holds:
+.cblk
(chr-str s i) --> (ref s i)
-
-.SS Function chr-str-set
-
-.TP
-Syntax:
-
- (chr-str-set <str> <idx> <char>)
-
-.TP
-Description:
-
-The chr-str function performs random access on string <str> to overwrite
-the character whose position is given by integer <idx>, which must
-be within range of the string. The character at <idx> is overwritten
-with character <char>.
-
-The <idx> argument works exactly as in chr-str.
-
-The <str> argument must be a modifiable string.
-
-.TP
-Notes:
-
-Direct use of chr-str is equivalent to the DWIM bracket notation except
-that <str> must be a string. The following relation holds:
-
+.cble
+
+.coNP Function @ chr-str-set
+.synb
+.mets (chr-str-set < str < idx << char )
+.syne
+.desc
+The
+.code chr-str
+function performs random access on string
+.meta str
+to overwrite
+the character whose position is given by integer
+.metn idx ,
+which must
+be within range of the string. The character at
+.meta idx
+is overwritten
+with character
+.metn char .
+
+The
+.meta idx
+argument works exactly as in
+.codn chr-str .
+
+The
+.meta str
+argument must be a modifiable string.
+
+.TP* Notes:
+
+Direct use of
+.code chr-str
+is equivalent to the DWIM bracket notation except
+that
+.meta str
+must be a string. The following relation holds:
+
+.cblk
(chr-str-set s i c) --> (set [s i] c)
+.cble
-since (set [s i] c) <--> (refset s i c), this also holds:
+since
+.codn (set [s i] c) <--> (refset s i c) ,
+this also holds:
+.cblk
(chr-str s i) --> (refset s i c)
+.cble
+
+.coNP Function @ span-str
+.synb
+.mets (span-str < str << set )
+.syne
+.desc
+The
+.code span-str
+function determines the longest prefix of string
+.meta str
+which
+consists only of the characters in string
+.metn set ,
+in any combination.
+
+.coNP Function @ compl-span-str
+.synb
+.mets (compl-span-str < str << set )
+.syne
+.desc
+The
+.code compl-span-str
+function determines the longest prefix of string
+.meta str
+which
+consists only of the characters which do not appear in
+.metn set ,
+in any combination.
+
+.coNP Function @ break-str
+.synb
+.mets (break-str < str << set )
+.syne
+.desc
+The
+.code break-str
+function returns an integer which represents the position of the
+first character in string
+.meta str
+which appears in string
+.metn set .
+
+If there is no such character, then
+.code nil
+is returned.
-.SS Function span-str
-
-.TP
-Syntax:
-
- (span-str <str> <set>)
-
-.TP
-Description:
-
-The span-str function determines the longest prefix of string <str> which
-consists only of the characters in string <set>, in any combination.
-
-.SS Function compl-span-str
-
-.TP
-Syntax:
-
- (compl-span-str <str> <set>)
-
-.TP
-Description:
-
-The compl-span-str function determines the longest prefix of string <str> which
-consists only of the characters which do not appear in <set>, in any
-combination.
-
-.SS Function break-str
-
-.TP
-Syntax:
-
- (break-str <str> <set>)
-
-.TP
-Description:
-
-The break-str function returns an integer which represents the position of the
-first character in string <str> which appears in string <set>.
-
-If there is no such character, then nil is returned.
-
-.SH LAZY STRINGS
-
+.SS* Lazy Strings
Lazy strings are objects that were developed for the TXR pattern matching
language, and are exposed via TXR Lisp. Lazy strings behave much like strings,
and can be substituted for strings. However, unlike regular strings, which
@@ -10144,19 +16144,28 @@ enough material, then the access fails, just like an access beyond the end of a
regular string. A lazy string always takes whole strings from the attached
list.
-Lazy string growth is achieved via the lazy-str-force-upto function which
+Lazy string growth is achieved via the
+.code lazy-str-force-upto
+function which
forces a string to exist up to a given character position. This function is
used internally to handle various situations.
-The lazy-str-force function forces the entire string to materialize. If the
+The
+.code lazy-str-force
+function forces the entire string to materialize. If the
string is connected to an infinite lazy list, this will exhaust all memory.
Lazy strings are specially recognized in many of the regular string functions,
-which do the right thing with lazy strings. For instance when sub-str
-is invoked on a lazy string, a special version of the sub-str logic is
+which do the right thing with lazy strings. For instance when
+.code sub-str
+is invoked on a lazy string, a special version of the
+.code sub-str
+logic is
used which handles various lazy string cases, and can potentially return
-another lazy string. Taking a sub-str of a lazy string from character position
-7 to all the way to the end does not force the entire lazy string to exist,
+another lazy string. Taking a
+.code sub-str
+of a lazy string from a given character position
+to the end does not force the entire lazy string to exist,
and in fact the operation will work on a lazy string that is infinite.
Furthermore, special lazy string functions are provided which allow programs to
@@ -10165,166 +16174,193 @@ means is code that avoids unnecessarily forcing the lazy string. For instance,
in many situations it is necessary to obtain the length of a string, only to
test it for equality or inequality with some number. But it is not necessary to
compute the length of a string in order to know that it is greater than some
-value. Computing the length of a lazy string is bad, because it forces the
-string to exist, which may not even be possible.
-
-.SS Function lazy-str
-
-.TP
-Syntax:
-
- (lazy-str <string-list> [<terminator> [<limit-count>]])
-
-.TP
-Description:
-
-The lazy-str function constructs a lazy string which draws material from
-<string-list> which is a list of strings.
+value.
-If the optional <terminator> argument is given, then it specifies a string
-which is appended to every string from <string-list>, before that string is
-incorporated into the lazy string. If <terminator> is not given,
-then it defaults to the string "\en", and so the strings from
-<string-list> are effectively treated as lines which get terminated by newlines
+.coNP Function @ lazy-str
+.synb
+.mets (lazy-str < string-list >> [ terminator <> [ limit-count ]])
+.syne
+.desc
+The
+.code lazy-str
+function constructs a lazy string which draws material from
+.meta string-list
+which is a list of strings.
+
+If the optional
+.meta terminator
+argument is given, then it specifies a string
+which is appended to every string from
+.metn string-list ,
+before that string is
+incorporated into the lazy string. If
+.meta terminator
+is not given,
+then it defaults to the string
+.strn "\en" ,
+and so the strings from
+.meta string-list
+are effectively treated as lines which get terminated by newlines
as they accumulate into the growing prefix of the lazy string.
-To avoid the use of a terminator string, a null string <terminator> argument
+To avoid the use of a terminator string, a null string
+.meta terminator
+argument
must be explicitly passed. In that case, the lazy string grows simply
-by catenating elements from <string-list>.
+by catenating elements from
+.metn string-list .
-If the <limit-count> argument is specified, it must be a positive integer. It
+If the
+.meta limit-count
+argument is specified, it must be a positive integer. It
expresses a maximum limit on how many elements will be consumed from
-<string-list> in order to feed the lazy string. Once that many elements are
+.meta string-list
+in order to feed the lazy string. Once that many elements are
drawn, the string ends, even if the list has not been exhausted.
-.SS Function lazy-stringp
-
-.TP
-Syntax:
-
- (lazy-stringp <obj>)
-
-.TP
-Description:
-
-The lazy-stringp function returns t if <obj> is a lazy
-string. Otherwise it returns nil.
-
-.SS Function lazy-str-force-upto
-
-.TP
-Syntax:
-
- (lazy-str-force-upto <lazy-str> <index>)
-
-.TP
-Description:
-
-The lazy-str-force-upto function tries to instantiate the lazy string such that
-the position given by <index> materializes. The <index> is a character
-position, exactly as used in the chr-str function.
+.coNP Function @ lazy-stringp
+.synb
+.mets (lazy-stringp << obj )
+.syne
+.desc
+The
+.code lazy-stringp
+function returns
+.code t
+if
+.meta obj
+is a lazy
+string. Otherwise it returns
+.codn nil .
+
+.coNP Function @ lazy-str-force-upto
+.synb
+.mets (lazy-str-force-upto < lazy-str << index )
+.syne
+.desc
+The
+.code lazy-str-force-upto
+function tries to instantiate the lazy string such that
+the position given by
+.meta index
+materializes. The
+.meta index
+is a character
+position, exactly as used in the
+.code chr-str
+function.
-Some positions beyond <index> may also materialize, as a side effect.
+Some positions beyond
+.meta index
+may also materialize, as a side effect.
-If the string is already materialized through to at least <index>, or if it is
-possible to materialize the string that far, then the value t is returned to
-indicate success.
+If the string is already materialized through to at least
+.metn index ,
+or if it is
+possible to materialize the string that far, then the value
+.code t
+is returned to indicate success.
If there is insufficient material to force the lazy string through to the
-<index> position, then nil is returned.
-
-It is an error if the <lazy-str> argument isn't a lazy string.
-
-.SS Function lazy-str-force
-
-.TP
-Syntax:
-
- (lazy-str-force <lazy-str>)
-
-.TP
-Description:
-
-The <lazy-str> argument must be a lazy string. The lazy string is forced
+.meta index
+position, then nil is returned.
+
+It is an error if the
+.meta lazy-str
+argument isn't a lazy string.
+
+.coNP Function @ lazy-str-force
+.synb
+.mets (lazy-str-force << lazy-str )
+.syne
+.desc
+The
+.meta lazy-str
+argument must be a lazy string. The lazy string is forced
to fully materialize.
The return value is an ordinary, non-lazy string equivalent to the fully
materialized lazy string.
-.SS Function lazy-str-get-trailing-list
-
-.TP
-Syntax:
-
- (lazy-str-get-trailing-list <string> <index>)
-
-.TP
-Description:
-
-The lazy-str-get-trailing-list function is a sort of inverse operation to
+.coNP Function @ lazy-str-get-trailing-list
+.synb
+.mets (lazy-str-get-trailing-list < string << index )
+.syne
+.desc
+The
+.code lazy-str-get-trailing-list
+function is a sort of inverse operation to
the lazy string from its associated list.
-Firstly, the string is forced up through the position <index>.
+First, the string is forced up through the position
+.metn index .
-Next, the materialized part of the string starting at position <index>,
+Next, the materialized part of the string starting at position
+.metn index ,
through to the end, is split into pieces on occurrences of the terminator
-character, which had been given as the <terminator> argument in the lazy-str
+character, which had been given as the
+.meta terminator
+argument in the
+.code lazy-str
constructor, and defaults to the newline character.
Finally, a list is returned consisting of the pieces produced by the split,
to which is appended the remaining list of the string which has not yet been
forced to materialize.
-If <index> is a position which cannot be forced, then the lazy string's
+If
+.meta index
+is a position which cannot be forced, then the lazy string's
remaining list is returned, with single null string prepended to it.
-
-.SS Functions length-str->, length-str->=, length-str-< and length-str-<=
-
-.TP
-Syntax:
-
- (length-str-> <string> <len>)
- (length-str->= <string> <len>)
- (length-str-< <string> <len>)
- (length-str-<= <string> <len>)
-
-.TP
-Description:
-
+.coNP Functions @, length-str-> @, length-str->= @ length-str-< and @ length-str-<=
+.synb
+.mets (length-str-> < string << len )
+.mets (length-str->= < string << len )
+.mets (length-str-< < string << len )
+.mets (length-str-<= < string << len )
+.syne
+.desc
These functions compare the lengths of two strings. The following
equivalences hold, as far as the resulting value is concerned:
+.cblk
(length-str-> s l) <--> (> (length-str s) l)
(length-str->= s l) <--> (>= (length-str s) l)
(length-str-< s l) <--> (< (length-str s) l)
(length-str-<= s l) <--> (<= (length-str s) l)
+.cble
-The difference between the length-str-* functions and the equivalent forms is
-that if the string is lazy, the length-str function will fully force it in
-order to calculate and return its length.
+The difference between the functions and the equivalent forms is that if the
+string is lazy, the
+.code length-str
+function will fully force it in order to
+calculate and return its length.
-These functions only force a string up to position <len>, so they are not
-only more efficient, but usable on infinitely long lazy strings.
+These functions only force a string up to position
+.metn len ,
+so they are not
+only more efficient, but on infinitely long lazy strings they are usable.
-length-str cannot compute the length of a lazy string with an unbounded
+.code length-str
+cannot compute the length of a lazy string with an unbounded
length; it will exhaust all memory trying to force the string.
These functions can be used to test such as string whether it is longer
or shorter than a given length, without forcing the string beyond
that length.
-.SS Function cmp-str
-
-.TP
-Syntax:
-
- (cmp-str <left-string> <right-string>)
-
-.TP
-Semantics:
-
-The cmp-str function returns a negative integer if <left-string>
-is lexicographically prior to <right-string>, and a positive integer
+.coNP Function @ cmp-str
+.synb
+.mets (cmp-str < left-string << right-string )
+.syne
+.desc
+The
+.code cmp-str
+function returns a negative integer if
+.meta left-string
+is lexicographically prior to
+.metn right-string ,
+and a positive integer
if the reverse situation is the case. Otherwise the strings are equal
and zero is returned.
@@ -10337,708 +16373,1032 @@ The lexicographic ordering is naive, based on the character code point
values in Unicode taken as integers, without regard for locale-specific
collation orders.
-.SS Functions str=, str<, str>, str>= and str<=
-
-.TP
-Syntax:
-
- (str= <left-string> <right-string>)
- (str< <left-string> <right-string>)
- (str> <left-string> <right-string>)
- (str<= <left-string> <right-string>)
- (str>= <left-string> <right-string>)
-
-.TP
-Semantics:
-
-These functions compare <left-string> and <right-string> lexicographically,
-as if by the cmp-str function.
-
-The str= function returns t if the two strings are exactly the same, character
-for character, otherwise it returns nil.
-
-The str< function returns t if <left-string> is lexicographically before
-<right-string>, otherwise nil.
-
-The str> function returns t if <left-string> is lexicographically after
-<right-string>, otherwise nil.
-
-The str< function returns t if <left-string> is lexicographically before
-<right-string>, or if they are exactly the same, otherwise nil.
-
-The str< function returns t if <left-string> is lexicographically after
-<right-string>, or if they are exactly the same, otherwise nil.
-
-.SS Function string-lt
-
-.TP
-Syntax:
-
- (string-lt <left-str> <right-str>)
-
-.TP
-Description:
-
-The string-lt is a deprecated alias for str<.
-
-.SH VECTORS
-
-.SS Function vector
-
-.TP
-Syntax:
-
- (vector <length> [<initval>])
-
-.TP
-Description:
-
-The vector function creates and returns a vector object of the specified
-length. The elements of the vector are initialized to <initval>,
-or to nil if <initval> is omitted.
-
-.SS Function vec
-
-.TP
-Syntax:
-
- (vec . <args>)
-
-.TP
-Description:
-
-The vec function creates a vector out of its arguments.
-
-.SS Function vectorp
-
-.TP
-Syntax:
-
- (vectorp <obj>)
-
-.TP
-Description:
-
-The vectorp function returns t if <obj> is a vector, otherwise it returns
-nil.
-
-.SS Function vec-set-length
-
-.TP
-Syntax:
-
- (vec-set-length <vec> <len>)
+.coNP Functions @, str= @, str< @, str> @ str>= and @ str<=
+.synb
+.mets (str= < left-string << right-string )
+.mets (str< < left-string << right-string )
+.mets (str> < left-string << right-string )
+.mets (str<= < left-string << right-string )
+.mets (str>= < left-string << right-string )
+.syne
+.desc
+These functions compare
+.meta left-string
+and
+.meta right-string
+lexicographically,
+as if by the
+.code cmp-str
+function.
-.TP
-Description:
+The
+.code str=
+function returns
+.code t
+if the two strings are exactly the same, character
+for character, otherwise it returns
+.codn nil .
+
+The
+.code str<
+function returns
+.code t
+if
+.meta left-string
+is lexicographically before
+.metn right-string ,
+otherwise nil.
-The vec-set-length modifies the length of <vec>, making it longer or
+The
+.code str>
+function returns
+.code t
+if
+.meta left-string
+is lexicographically after
+.metn right-string ,
+otherwise
+.codn nil .
+
+The
+.code str<
+function returns
+.code t
+if
+.meta left-string
+is lexicographically before
+.metn right-string ,
+or if they are exactly the same, otherwise
+.codn nil .
+
+The
+.code str<
+function returns
+.code t
+if
+.meta left-string
+is lexicographically after
+.metn right-string ,
+or if they are exactly the same, otherwise
+.codn nil .
+
+.coNP Function @ string-lt
+.synb
+.mets (string-lt < left-str << right-str )
+.syne
+.desc
+The
+.code string-lt
+is a deprecated alias for
+.codn str< .
+
+.SS* Vectors
+.coNP Function @ vector
+.synb
+.mets (vector < length <> [ initval ])
+.syne
+.desc
+The
+.code vector
+function creates and returns a vector object of the specified
+length. The elements of the vector are initialized to
+.metn initval ,
+or to nil if
+.meta initval
+is omitted.
+
+.coNP Function @ vec
+.synb
+.mets (vec << arg *)
+.syne
+.desc
+The
+.code vec
+function creates a vector out of its arguments.
+
+.coNP Function @ vectorp
+.synb
+.mets (vectorp << obj )
+.syne
+.desc
+The
+.code vectorp
+function returns t if
+.meta obj
+is a vector, otherwise it returns
+.codn nil .
+
+.coNP Function @ vec-set-length
+.synb
+.mets (vec-set-length < vec << len )
+.syne
+.desc
+The
+.code vec-set-length
+modifies the length of
+.metn vec ,
+making it longer or
shorter. If the vector is made longer, then the newly added elements
-are initialized to nil. The <len> argument must be nonnegative.
-
-The return value is <vec>.
-
-.SS Function vecref
-
-.TP
-Syntax:
-
- (vecref <vec> <idx>)
-
-.TP
-Description:
-
-The vecref function performs indexing into a vector. It retrieves
-an element of <vec> at position <idx>, counted from zero.
-The <idx> value must range from 0 to one less than the
+are initialized to nil. The
+.meta len
+argument must be nonnegative.
+
+The return value is
+.metn vec .
+
+.coNP Function @ vecref
+.synb
+.mets (vecref < vec << idx )
+.syne
+.desc
+The
+.code vecref
+function performs indexing into a vector. It retrieves
+an element of
+.meta vec
+at position
+.metn idx ,
+counted from zero.
+The
+.meta idx
+value must range from 0 to one less than the
length of the vector. The specified element is returned.
-.SS Function vec-push
-
-.TP
-Syntax:
-
- (vec-push <vec> <elem>)
-
-.TP
-Description:
-
-The vec-push function extends the length of a vector <vec> by one element, and
-sets the new element to the value <elem>.
-
-The previous length of the vector (which is also the position of <elem>)
+.coNP Function @ vec-push
+.synb
+.mets (vec-push < vec << elem )
+.syne
+.desc
+The
+.code vec-push
+function extends the length of a vector
+.meta vec
+by one element, and
+sets the new element to the value
+.metn elem .
+
+The previous length of the vector (which is also the position of
+.metn elem )
is returned.
-This function performs similarly to the generic function ref, except that the
+This function performs similarly to the generic function
+.codn ref ,
+except that the
first argument must be a vector.
-.SS Function length-vec
-
-.TP
-Syntax:
-
- (length-vec <vec>)
-
-.TP
-Description:
-
-The length-vec function returns the length of vector <vec>. It performs
-similarly to the generic length function, except that the argument must
+.coNP Function @ length-vec
+.synb
+.mets (length-vec << vec )
+.syne
+.desc
+The
+.code length-vec
+function returns the length of vector
+.metn vec .
+It performs
+similarly to the generic
+.code length
+function, except that the argument must
be a vector.
-.SS Function size-vec
-
-.TP
-Syntax:
-
- (size-vec <vec>)
-
-.TP
-Description:
-
-The size-vec function returns the number of elements for which storage
-is reserved in the vector vec.
-
-.TP
-Notes:
-
-The length of the vector can be extended up to this size without any memory
+.coNP Function @ size-vec
+.synb
+.mets (size-vec << vec )
+.syne
+.desc
+The
+.code size-vec
+function returns the number of elements for which storage
+is reserved in the vector
+.metn vec .
+
+.TP* Notes:
+
+The
+.code length
+of the vector can be extended up to this size without any memory
allocation operations having to be performed.
-.SS Function vector-list
-
-.TP
-Syntax:
-
- (vector-list <list>)
-
-.TP
-Description:
-
+.coNP Function @ vector-list
+.synb
+.mets (vector-list << list )
+.syne
+.desc
This function returns a vector which contains all of the same elements
-and in the same order as list <list>.
-
-.SS Function list-vector
-
-.TP
-Syntax:
-
- (list-vector <vec>)
-
-.TP
-Description:
-
-The list-vector function returns a list of the elements of vector <vec>.
-
-.SS Function copy-vec
-
-.TP
-Syntax:
-
- (copy-vec <vec>)
-
-.TP
-Description:
-
-The copy-vec function returns a new vector object of the same length
-as <vec> and containing the same elements in the same order.
-
-.SS Function sub-vec
-
-.TP
-Syntax:
-
- (sub-vec <vec> [<from> [<to>]])
-
-.TP
-Description:
-
-The sub-vec function is like the more generic function sub, except that it
+and in the same order as list
+.metn list .
+
+.coNP Function @ list-vector
+.synb
+.mets (list-vector << vec )
+.syne
+.desc
+The
+.code list-vector
+function returns a list of the elements of vector
+.metn vec .
+
+.coNP Function @ copy-vec
+.synb
+.mets (copy-vec << vec )
+.syne
+.desc
+The
+.code copy-vec
+function returns a new vector object of the same length
+as
+.meta vec
+and containing the same elements in the same order.
+
+.coNP Function @ sub-vec
+.synb
+.mets (sub-vec < vec >> [ from <> [ to ]])
+.syne
+.desc
+The
+.code sub-vec
+function is like the more generic function
+.codn sub ,
+except that it
operates only on vectors.
-For a description of the arguments and semantics, refer to the sub function.
-
-.SS Function replace-vec
-
-.TP
-Syntax:
-
- (replace-vec <vec> <item-sequence> [<from> [<to>]])
-
-.TP
-Description:
+For a description of the arguments and semantics, refer to the
+.code sub
+function.
-The replace-vec is like the replace function, except that the first argument
+.coNP Function @ replace-vec
+.synb
+.mets (replace-vec < vec < item-sequence >> [ from <> [ to ]])
+.syne
+.desc
+The
+.code replace-vec
+is like the
+.code replace
+function, except that the first argument
must be a vector.
-For a description of the arguments and semantics, refer to the replace function.
-
-.SS Function cat-vec
-
-.TP
-Syntax:
-
- (cat-vec <vec-list>)
-
-.TP
-Description:
+For a description of the arguments and semantics, refer to the
+.code replace
+function.
-The <vec-list> argument is a list of vectors. The cat-vec function
-produces a catenation of the vectors listed in <vec-list>. It returns
+.coNP Function cat-vec
+.synb
+.mets (cat-vec << vec-list )
+.syne
+.desc
+The
+.meta vec-list
+argument is a list of vectors. The
+.code cat-vec
+function
+produces a catenation of the vectors listed in
+.metn vec-list .
+It returns
a single large vector formed by catenating those vectors together in
order.
-.SH SEQUENCE MANIPULATION
-
-.SS Function seqp
-
-.TP
-Syntax:
-
- (seqp <object>)
-
-.TP
-Description:
-
-The function seqp returns t if <object> is a sequence, otherwise nil.
-
-A sequence is defined as a list, vector or string. The object nil denotes
+.SS* Sequence Manipulation
+.coNP Function @ seqp
+.synb
+.mets (seqp << object )
+.syne
+.desc
+The function
+.code seqp
+returns
+.code t
+if
+.meta object
+is a sequence, otherwise
+.codn nil .
+
+A sequence is defined as a list, vector or string. The object
+.code nil
+denotes
the empty list and so is a sequence.
-.SS Function length
-
-.TP
-Syntax:
-
- (length <sequence>)
-
-.TP
-Description:
-
-The length function returns the number of items in <sequence>, and
-returns it. <sequence> may be a hash, in which case (hash-count <sequence>) is
-returned.
-
-.SS Function empty
-
-.TP
-Syntax:
-
- (empty <sequence>)
-
-.TP
-Description:
-
-Returns t if (length <sequence>) is zero, otherwise nil.
-
-.SS Function copy
-
-.TP
-Syntax:
-
- (copy <sequence>)
-
-.TP
-Description:
-
-The copy function duplicates a sequence. If <sequence> is nil, it
-returns nil. If <sequence> is a list, it returns (copy-list <sequence>);
-if <sequence> is a string, it returns (copy-str <sequence>);
-if <sequence> is a vector, it returns (copy-vec <sequence>); and
-if <sequence> is a hash, it return (copy-hash <sequence>).
+.coNP Function @ length
+.synb
+.mets (length << sequence )
+.syne
+.desc
+The
+.code length
+function returns the number of items in
+.metn sequence ,
+and
+returns it.
+.meta sequence
+may be a hash, in which case (hash-count
+.metn sequence )
+is returned.
-Except in the case when <sequence> is nil, copy returns a value that
-is distinct from (not eq to) <sequence>. This is different from
-the behavior of [<sequence> 0..t] or (sub <sequence> 0 t), which recognize
-that they need not make a copy of <sequence>, and just return it.
+.coNP Function @ empty
+.synb
+.mets (empty << sequence )
+.syne
+.desc
+Returns
+.code t
+if
+.cblk
+.meti (length << sequence )
+.cble
+is zero, otherwise
+.codn nil .
+
+.coNP Function @ copy
+.synb
+.mets (copy << sequence )
+.syne
+.desc
+The
+.code copy
+function duplicates a sequence. If
+.meta sequence
+is
+.codn nil ,
+it
+returns
+.codn nil .
+If
+.meta sequence
+is a list, it returns
+.cblk
+.meti (copy-list << sequence ).
+.cble
+If
+.meta sequence
+is a string, it returns
+.cblk
+.meti (copy-str << sequence ).
+.cble
+If
+.meta sequence
+is a vector, it returns
+.cblk
+.meti (copy-vec << sequence ).
+.cble
+If
+.meta sequence
+is a hash, it returns
+.cblk
+.meti (copy-hash << sequence ).
+.cble
+
+Except in the case when
+.meta sequence
+is
+.codn nil ,
+.code copy
+returns a value that
+is distinct from (not
+.code eq
+to)
+.metn sequence .
+This is different from
+the behavior of
+.cblk
+.meti >> [ sequence 0..t]
+.cblk
+or
+.cblk
+.meti (sub < sequence 0 t)
+.cble
+which recognize
+that they need not make a copy of
+.metn sequence ,
+and just return it.
Note however, that the elements of the returned sequence may be
eq to elements of the original sequence. In other words, copy is
-a deeper copy than just duplicating the <sequence> value itself,
+a deeper copy than just duplicating the
+.code sequence
+value itself,
but it is not a deep copy.
-.SS Function sub
-
-.TP
-Syntax:
-
- (sub <sequence> [<from> [<to>]])
-
-Description:
-
-The sub function extracts a slice from input sequence <sequence>. The slice is
-a sequence of the same type as <sequence>.
-
-If the <from> argument is omitted, it defaults to 0. If the <to> parameter is
-omitted, it defaults to t. Thus (sub a) means (sub a 0 t).
-
-The following equivalence holds between the sub function and
+.coNP Function @ sub
+.synb
+.mets (sub < sequence >> [ from <> [ to ]])
+.syne
+.desc
+The
+.code sub
+function extracts a slice from input sequence
+.metn sequence .
+The slice is
+a sequence of the same type as
+.metn sequence .
+
+If the
+.meta from
+argument is omitted, it defaults to
+.codn 0 .
+If the
+.meta to
+parameter is
+omitted, it defaults to
+.codn t .
+Thus
+.code (sub a)
+means
+.codn (sub a 0 t) .
+
+The following equivalence holds between the
+.code sub
+function and
the DWIM-bracket syntax:
+.cblk
;; from is not a list
(sub seq from to) <--> [seq from..to]
+.cble
-The description of the dwim operator - in particular, the section
-on Range Indexing - explains the semantics of the range specification.
+The description of the
+.code dwim
+operator\(emin particular, the section
+on Range Indexing\(emexplains the semantics of the range specification.
If the sequence is a list, the output sequence may share substructure
with the input sequence.
-.SS Function replace
-
-.TP
-Syntax:
-
- (replace <sequence> <replacement-sequence> [<from> [<to>]])
- (replace <sequence> <replacement-sequence> <index-list>)
-
-.TP
-Description:
-
-The replace function has two invocation styles, distinguished by the
-type of the third argument. If the third argument is a list,
-then it is deemed to be the <index-list> parameter of the second form.
+.coNP Function @ replace
+.synb
+.mets (replace < sequence < replacement-sequence >> [ from <> [ to ]])
+.mets (replace < sequence < replacement-sequence << index-list )
+.syne
+.desc
+The
+.code replace
+function has two invocation styles, distinguished by the
+type of the third argument. If the third argument is a list, then it is deemed to be the
+.meta index-list
+parameter of the second form.
Otherwise, if the third argument is missing, or is not a list, then
-it is deemed to be the <from> argument of the first form.
+it is deemed to be the
+.meta from
+argument of the first form.
The first form of the replace function replaces a contiguous subsequence of the
-<sequence> with <replacement-sequence>. The replaced subsequence may be empty,
-in which case an insertion is performed. If <replacement-sequence> is empty
-(for example, the empty list nil), then a deletion is performed.
-
-If the <from> and <to> arguments are omitted, their values default
-to 0 and t respectively.
+.meta sequence
+with
+.metn replacement-sequence .
+The replaced subsequence may be empty,
+in which case an insertion is performed. If
+.meta replacement-sequence
+is empty
+(for example, the empty list
+.codn nil ),
+then a deletion is performed.
+
+If the
+.meta from
+and
+.meta to
+arguments are omitted, their values default
+to
+.code 0
+and
+.code t
+respectively.
The following equivalence holds between assignment to a place denoted by
DWIM bracket syntax and first form of the replace function:
- (set seq (replace seq new from to)) <--> (set [seq from..to] new)
+.cblk
+ (set seq (replace seq new fr to)) <--> (set [seq fr..to] new)
+.cble
-The description of the dwim operator - in particular, the section
-on Range Indexing - explains the semantics of the range specification.
+The description of the dwim operator\(emin particular, the section
+on Range Indexing\(emexplains the semantics of the range specification.
This operation is destructive: it may work "in place" by modifying
the original sequence. The caller should retain the return value
and stop relying on the original input sequence.
The second form of the replace function replaces a subsequence of
-elements from <sequence> given by <index-list>, with their counterparts
-from <replacement-sequence>. This form of the replace function does not insert
-or delete; it simply overwrites elements. If <replacement-sequence> and
-<index-list> are of different lengths, then the shorter of the two determines
+elements from
+.meta sequence
+given by
+.metn index-list ,
+with their counterparts
+from
+.metn replacement-sequence .
+This form of the replace function does not insert
+or delete; it simply overwrites elements. If
+.meta replacement-sequence
+and
+.meta idex-list
+are of different lengths, then the shorter of the two determines
the maximum number of elements which are overwritten.
-Furthermore, similar restrictions apply on <index-list> as under the
+Furthermore, similar restrictions apply on
+.meta index-list
+as under the
select function. Namely, the replacement stops when an index value
-in <index-list> is encountered which is out of range for <sequence>.
-Furthermore, if <sequence> is a list, then <index-list> must
+in
+.meta index-list
+is encountered which is out of range for
+.metn sequence .
+furthermore, if
+.meta sequence
+is a list, then
+.meta index-list
+must
be monotonically increasing.
The following equivalence holds between assignment to a place denoted by
-DWIM bracket syntax and second form of the replace function:
-
- (set seq (replace seq new index-list)) <--> (set [seq index-list] new)
-
-.SS Function search
-
-.TP
-Syntax:
-
- (search <haystack> <needle> [<testfun> [<keyfun>])
-
-.TP
-Description:
-
-The search function determines whether the sequence <needle> occurs as substring
-within <haystack>, under the given comparison function <testfun> and
-key function <keyfun>. If this is the case, then the zero-based position of
-the leftmost occurrence of <key> within <haystack> is returned. Otherwise nil
-is returned to indicate that <key> does not occur within <haystack>.
-If <key> is empty, then zero is always returned.
-
-The arguments <haystack> and <needle> are sequences: lists, vectors
+DWIM bracket syntax and second form of the
+.code replace
+function:
+
+.cblk
+ (set seq (replace seq new ix-list)) <--> (set [seq ix-list] new)
+.cble
+
+.coNP Function @ search
+.synb
+.mets (search < haystack < needle >> [ testfun <> [ keyfun ])
+.syne
+.desc
+The
+.code search
+function determines whether the sequence
+.meta needle
+occurs as substring
+within
+.metn haystack ,
+under the given comparison function
+.meta testfun
+and
+key function
+.metn keyfun .
+If this is the case, then the zero-based position of
+the leftmost occurrence of
+.meta key
+within
+.meta haystack
+is returned. Otherwise
+.code nil
+is returned to indicate that
+.meta key
+does not occur within
+.metn haystack .
+If
+.meta key
+is empty, then zero is always returned.
+
+The arguments
+.meta haystack
+and
+.meta needle
+are sequences: lists, vectors
or strings, in any combination.
-If <needle> is not empty, then occurs at some position N within <haystack> if
-the first element of <needle> matches the element at position N of <haystack>,
-the second element of <needle> matches the element at position N+1 of
-<haystack> and so forth, for all elements of <needle>. A match between elements
-is determined by passing each element through <keyfun>, and then comparing
-the resulting values using <testfun>.
+If
+.meta needle
+is not empty, then occurs at some position N within
+.meta haystack
+if
+the first element of
+.meta needle
+matches the element at position N of
+.metn haystack ,
+the second element of
+.meta needle
+matches the element at position N+1 of
+.meta haystack
+and so forth, for all elements of
+.metn needle .
+A match between elements
+is determined by passing each element through
+.metn keyfun ,
+and then comparing the resulting values using
+.metn testfun .
-If <testfun> is supplied, it must be a function which can be
-called with two arguments. If it is not supplied, it defaults to eql.
+If
+.meta testfun
+is supplied, it must be a function which can be
+called with two arguments. If it is not supplied, it defaults to
+.codn eql .
-If <keyfun> is supplied, it must be a function which can be called
-with one argument. If it is not supplied, it defaults to identity.
+If
+.meta keyfun
+is supplied, it must be a function which can be called
+with one argument. If it is not supplied, it defaults to
+.codn identity .
-.TP
-Examples:
+.TP* Examples:
- ;; fails because 3.0 doesn't match 3 under the default eql function
+.cblk
+ ;; fails because 3.0 doesn't match 3
+ ;; under the default eql function
[search #(1.0 3.0 4.0 7.0) '(3 4)] -> nil
- ;; occurrence found at position 1: (3.0 4.0) matches (3 4) under =
+ ;; occurrence found at position 1:
+ ;; (3.0 4.0) matches (3 4) under =
[search #(1.0 3.0 4.0 7.0) '(3 4) =] -> 1
- ;; "even odd odd odd even" pattern matches at position 2
+ ;; "even odd odd odd even" pattern
+ ;; matches at position 2
[search #(1 1 2 3 5 7 8) '(2 1 1 1 2) : evenp] -> 2
;; Case insensitive string search
[search "abcd" "CD" : chr-toupper] -> 2
- ;; Case insensitive string search using vector of characters as key
+ ;; Case insensitive string search
+ ;; using vector of characters as key
[search "abcd" #(#\eC #\eD) : chr-toupper] -> 2
-
-.SS Functions ref and refset
-
-.TP
-Syntax:
-
- (ref <seq> <index>)
- (refset <seq> <index> <new-value>)
-
-.TP
-Description:
-
-The ref and refset functions perform array-like indexing into sequences.
-The ref function retrieves an element of <seq>, whereas refset overwrites an
-element of <seq> with a new value.
-
-The <index> argument is based from zero, and negative values are permitted,
+.cble
+
+.coNP Functions @ ref and @ refset
+.synb
+.mets (ref < seq << index )
+.mets (refset < seq < index << new-value )
+.syne
+.desc
+The
+.code ref
+and
+.code refset
+functions perform array-like indexing into sequences.
+The
+.code ref
+function retrieves an element of
+.metn seq ,
+whereas
+.code refset
+overwrites an
+element of
+.meta seq
+with a new value.
+
+The
+.meta index
+argument is based from zero, and negative values are permitted,
with a special meaning as described in the Range Indexing section under the
-description of the dwim operator.
+description of the
+.code dwim
+operator.
-The refset function returns the new value.
+The
+.code refset
+function returns the new value.
-The following equivalences hold between ref and refset, and the DWIM
-bracket syntax:
+The following equivalences hold between
+.code ref
+and
+.codn refset ,
+and the DWIM bracket syntax:
+.cblk
(ref seq idx) <--> [seq idx]
(refset seq idx new) <--> (set [seq idx] new)
+.cble
-The difference is that ref and refset are first class functions which
+The difference is that
+.code ref
+and
+.code refset
+are first class functions which
can be used in functional programming as higher order functions, whereas the
-bracket notation is syntactic sugar, and set is an operator, not a function.
-Therefore the brackets cannot replace all uses of ref and refset.
-
-.SS Function update
-
-.TP
-Syntax:
-
- (update <sequence-or-hash> <function>)
-
-.TP
-Description:
-
-The update function replaces each elements in a sequence, or each value
-in a hash table, with the value of <function> applied to that element
+bracket notation is syntactic sugar, and
+.code set
+is an operator, not a function.
+Therefore the brackets cannot replace all uses of
+.code ref
+and
+.codn refset .
+
+.coNP Function @ update
+.synb
+.mets (update < sequence-or-hash << function )
+.syne
+.desc
+The
+.code update
+function replaces each elements in a sequence, or each value
+in a hash table, with the value of
+.meta function
+applied to that element
or value.
The sequence or hash table is returned.
-.SS Function sort
-
-.TP
-Syntax:
-
- (sort <sequence> <lessfun> [<keyfun>])
-
-.TP
-Description:
-
-The sort function destructively sorts <sequence>, producing a sequence
-which is sorted according to the <lessfun> and <keyfun> arguments.
-
-The <keyfun> argument specifies a function which is applied to elements
+.coNP Function @ sort
+.synb
+.mets (sort < sequence < lessfun <> [ keyfun ])
+.syne
+.desc
+The
+.code sort
+function destructively sorts
+.metn sequence ,
+producing a sequence
+which is sorted according to the
+.meta lessfun
+and
+.meta keyfun
+arguments.
+
+The
+.meta keyfun
+argument specifies a function which is applied to elements
of the sequence to obtain the key values which are then compared
-using the lessfun. If <keyfun> is omitted, the identity function is used
+using the lessfun. If
+.meta keyfun
+is omitted, the identity function is used
by default: the sequence elements themselves are their own sort keys.
-The <lessfun> argument specifies the comparison function which determines
+The
+.meta lessfun
+argument specifies the comparison function which determines
the sorting order. It must be a binary function which can be invoked
on pairs of keys as produced by the key function. It must
-return a non-nil value if the left argument is considered to be lesser
-than the right argument. For instance, if the numeric function < is used
+return a
+.cod2 non- nil
+value if the left argument is considered to be lesser
+than the right argument. For instance, if the numeric function
+.code <
+is used
on numeric keys, it produces an ascending sorted order. If the function
-> is used, then a descending sort is produced.
+.code >
+is used, then a descending sort is produced.
-The sort function is stable for sequences which are lists. This means that the
+The
+.code sort
+function is stable for sequences which are lists. This means that the
original order of items which are considered identical is preserved.
-For strings and vectors, the sort is not stable.
-
-.SS Function uniq
-
-.TP
-Syntax:
-
- (uniq <sequence>)
-
-.TP
-Description:
-
-The uniq function returns a sequence of the same kind as <sequence>, but with
-duplicates removed. Elements of <sequence> are considered equal under
-the equal function. The first occurrence of each element is retained,
+For strings and vectors,
+.code sort
+is not stable.
+
+.coNP Function @ uniq
+.synb
+.mets (uniq << sequence )
+.syne
+.desc
+The
+.code uniq
+function returns a sequence of the same kind as
+.metn sequence ,
+but with
+duplicates removed. Elements of
+.meta sequence
+are considered equal under
+the
+.code equal
+function. The first occurrence of each element is retained,
and the subsequent duplicates of that element, of any, are suppressed,
such that the order of the elements is otherwise preserved.
-.SS Function tuples
-
-.TP
-Syntax:
-
- (tuples <length> <sequence> [<fill-value>])
-
-.TP
-Description:
-
-The tuples function produces a lazy list which represents a reorganization
-of the elements of <sequence> into tuples of <length>, where <length>
+.coNP Function @ tuples
+.synb
+.mets (tuples < length < sequence <> [ fill-value ])
+.syne
+.desc
+The
+.code tuples
+function produces a lazy list which represents a reorganization
+of the elements of
+.meta sequence
+into tuples of
+.metn length ,
+where
+.meta length
must be a positive integer.
The length of the sequence might not be evenly divisible by the tuple length.
-In this case, if a <fill-value> argument is specified, then the last tuple
-is padded with enough repetitions of <fill-value> to make it have <length>
-elements. If <fill-value> is not specified, then the last tuple is left
-shorter than <length>.
+In this case, if a
+.meta fill-value
+argument is specified, then the last tuple
+is padded with enough repetitions of
+.meta fill-value
+to make it have
+.meta length
+elements. If
+.meta fill-value
+is not specified, then the last tuple is left
+shorter than
+.metn length .
The output of the function is a list, but the tuples themselves are sequences
-of the same kind as <sequence>. If <sequence> is any kind of list, they
+of the same kind as
+.metn sequence .
+If
+.meta sequence
+is any kind of list, they
are lists, and not lazy lists.
-.TP
-Examples:
+.TP* Examples:
+.cblk
(tuples 3 #(1 2 3 4 5 6 7 8) 0) -> (#(1 2 3) #(4 5 6) #(7 8 0))
(tuples 3 "abc") -> ("abc")
(tuples 3 "abcd") -> ("abc" "d")
(tuples 3 "abcd" #\z) -> ("abc" "dzz")
(tuples 3 (list 1 2) #\z) -> ((1 2 #\z))
+.cble
-.SS Function partition-by
-
-.TP
-Syntax:
-
- (partition-by <function> <sequence>)
-
-.TP
-Description:
-
-If <sequence> is empty, then partition-by returns an empty list,
-and <function> is never called.
-
-Otherwise, partition-by returns a lazy list of partitions of the sequence
-<sequence>. Partitions are consecutive, non-empty sub-strings of <sequence>,
-of the same kind as <sequence>.
-
-The partitioning begins with the first element of <sequence> being is placed
-into a partition.
-
-The subsequent partitioning is done according to <function>, which is applied
-to each element of <sequence>. Whenever, for the next element, the function
+.coNP Function @ partition-by
+.synb
+.mets (partition-by < function << sequence )
+.syne
+.desc
+If
+.meta sequence
+is empty, then
+.code partition-by
+returns an empty list,
+and
+.meta function
+is never called.
+
+Otherwise,
+.code partition-by
+returns a lazy list of partitions of the sequence
+.metn sequence .
+Partitions are consecutive, non-empty sub-strings of
+.metn sequence ,
+of the same kind as
+.metn sequence .
+
+The partitioning begins with the first element of
+.meta sequence
+being placed into a partition.
+
+The subsequent partitioning is done according to
+.metn function ,
+which is applied
+to each element of
+.metn sequence .
+Whenever, for the next element, the function
returns the same value as it returned for the previous element, the
element is placed into the same partition. Otherwise, the next element
is placed into, and begins, a new partition.
-The return values of the calls to <function> are compared using the equal
+The return values of the calls to
+.meta function
+are compared using the
+.code equal
function.
-Note:
-
-.TP
-Examples:
-
- [partition-by identity '(1 2 3 3 4 4 4 5)] -> ((1) (2) (3 3) (4 4 4) (5))
-
- (partition-by (op = 3) #(1 2 3 4 5 6 7)) -> (#(1 2) #(3) #(4 5 6 7))
-
-
-.SS Function make-like
-
-.TP
-Syntax:
-
- (make-like <list> <ref-sequence>)
-
-.TP
-Description:
-
-The <list> argument must be a list. If <ref-sequence> is a sequence type,
-then <list> is converted to the same type of sequence and returned.
-Otherwise the original <list> is returned.
+.TP* Examples:
+
+.cblk
+ [partition-by identity '(1 2 3 3 4 4 4 5)] -> ((1) (2) (3 3)
+ (4 4 4) (5))
+
+ (partition-by (op = 3) #(1 2 3 4 5 6 7)) -> (#(1 2) #(3)
+ #(4 5 6 7))
+.cble
+
+.coNP Function @ make-like
+.synb
+.mets (make-like < list << ref-sequence )
+.syne
+.desc
+The
+.meta list
+argument must be a list. If
+.meta ref-sequence
+is a sequence type,
+then
+.meta list
+is converted to the same type of sequence and returned.
+Otherwise the original
+.meta list
+is returned.
-Note: the make-like function is a helper which supports the development of
+Note: the
+.code make-like
+function is a helper which supports the development of
unoptimized versions of a generic function that accepts any type of
sequence as input, and produces a sequence of the same type as output.
The implementation of such a function can internally accumulate a list, and
then convert the resulting list to the same type as an input value
-by using make-like.
-
-.SS Function nullify
-
-.TP
-Syntax:
-
- (nullify <sequence>)
-
-.TP
-Description:
-
-The nullify function returns nil if <sequence> is an empty sequence.
-Otherwise it returns <sequence> itself.
-
-Note: the nullify function is a helper to support unoptimized generic
-programming over sequences. Thanks to the generic behavior cdr, any
-sequence can be traversed using cdr functions, checking for the nil
+by using
+.codn make-like .
+
+.coNP Function @ nullify
+.synb
+.mets (nullify << sequence )
+.syne
+.desc
+The
+.code nullify
+function returns
+.code nil
+if
+.meta sequence
+is an empty sequence.
+Otherwise it returns
+.meta sequence
+itself.
+
+Note: the
+.code nullify
+function is a helper to support unoptimized generic
+programming over sequences. Thanks to the generic behavior of
+.codn cdr ,
+any sequence can be traversed using
+.code cdr
+functions, checking for the
+.code nil
value as a terminator. This, however, breaks for empty sequences which are not
-lists, because they are not equal to nil: to car and cdr they look like
-a one-element sequence containing nil. The nullify function reduces all empty
-sequences to nil, thereby correcting the behavior of code which traverses
-sequences using cdr, and tests for termination with nil.
-
-.SH MATH LIBRARY
-
-.SS Arithmetic functions +, -
-
-.TP
-Syntax:
-
- (+ <number>*)
- (- <number> <number>*)
- (* <number>*)
-
-.TP
-Description:
-
-The +, - and * functions perform addition, subtraction and multiplication,
-respectively. Additionally, the - function performs additive inverse.
-
-The + function requires zero or more arguments. When called with no
+lists, because they are not equal to
+.codn nil :
+to
+.code car
+and
+.code cdr
+they look like
+a one-element sequence containing
+.codn nil .
+The
+.code nullify
+function reduces all empty
+sequences to
+.codn nil ,
+thereby correcting the behavior of code which traverses
+sequences using
+.codn cdr ,
+and tests for termination with
+.codn nil .
+
+.SS* Math Library
+.coNP Arithmetic functions @ + and @ -
+.synb
+.mets (+ << number *)
+.mets (- < number << number *)
+.mets (* << number *)
+.syne
+.desc
+The
+.codn + ,
+.code -
+and
+.code *
+functions perform addition, subtraction and multiplication,
+respectively. Additionally, the
+.code -
+function performs additive inverse.
+
+The
+.code +
+function requires zero or more arguments. When called with no
arguments, it produces 0 (the identity element for addition), otherwise it
produces the sum over all of the arguments.
-Similarly, the * function requires zero or more arguments. When called
+Similarly, the
+.code *
+function requires zero or more arguments. When called
with no arguments, it produces 1 (the identity element for multiplication).
Otherwise it produces the product of all the arguments.
-The semantics of - changes from subtraction to additive inverse
+The semantics of
+.code -
+changes from subtraction to additive inverse
when there is only one argument. The argument is treated as a subtrahend,
against an implicit minuend of zero. When there are two or more
argument, the first one is the minuend, and the remaining are subtrahends.
When there are three or more operands, these operations are performed as if by
-binary operations, in a left-associative way. That is to say, (+ a b c) means
-(+ (+ a b) c). The sum of a b is computed first, and then this is added to c.
-Similarly (- a b c) means (- (- a b) c). First, b is subtracted from a, and
-then c is subtracted from that result.
+binary operations, in a left-associative way. That is to say,
+.code (+ a b c)
+means
+.codn (+ (+ a b) c) .
+The sum of
+.code a
+and
+.code b
+is computed first, and then this is added to
+.codn c .
+Similarly
+.code (- a b c)
+means
+.codn (- (- a b) c) .
+First,
+.code b
+is subtracted from
+.codn a ,
+and then
+.code c
+is subtracted from that result.
The arithmetic inverse is performed as if it were subtraction from integer 0.
-That is, (- x) means the same thing as (- 0 x).
-
-The operands of +, - and * can be characters, integers (fixnum and bignum), and
+That is,
+.code (- x)
+means the same thing as
+.codn (- 0 x) .
+
+The operands of
+.codn + ,
+.code -
+and
+.code *
+can be characters, integers (fixnum and bignum), and
floats, in nearly any combination.
If two operands have different types, then one of them is converted to the
@@ -11046,190 +17406,275 @@ type of the one with the higher rank, according to this ranking:
character < integer < float. For instance if one operand is integer, and the
other float, the integer is converted to a float.
-.TP
-Restrictions:
+.TP* Restrictions:
Characters are not considered numbers, and participate in these operations in
limited ways. Subtraction can be used to computed the displacement between the
Unicode values of characters, and an integer displacement can be added to a
-character, or subtracted from a character. For instance (- #\e9 #\e0) is 9.
-The Unicode value of a character C can be found using (- C #\ex0): the
-displacement from the NUL character.
+character, or subtracted from a character. For instance
+.codn (- #\e9 #\e0) is 9 .
+The Unicode value of a character
+.code C
+can be found using
+.codn (- C #\ex0) :
+the displacement from the NUL character.
The rules can be stated as a set of restrictions:
-
+.RS
+.IP 1
Two characters may not be added together.
-
+.IP 2
A character may not be subtracted from an integer (which also rules out
the possibility of computing the additive inverse of a character).
-
+.IP 3
A character operand may not be opposite to a floating point operand
in any operation.
-
+.IP 4
A character may not be an operand of multiplication.
+.RE
-.SS Functions /, trunc, mod
-
-.TP
-Syntax:
-
- (/ [<dividend>] <divisor>)
- (trunc <dividend> <divisor>)
- (mod <dividend> <divisor>)
-
-Description:
+.PP
+.coNP Functions @, / @ trunc and @ mod
+.synb
+.mets (/ <> [ dividend ] << divisor )
+.mets (trunc < dividend << divisor )
+.mets (mod < dividend << divisor )
+.syne
+.desc
The arguments to these functions are numbers. Characters are not permitted.
-The / function performs floating-point division. Each operands is first
-converted to floating-point type, if necessary. If <dividend> is omitted,
-then it is taken to be 1.0 and the function performs a reciprocal.
-
-The trunc function performs a division of <dividend> by <divisor> whose result
+The
+.code /
+function performs floating-point division. Each operands is first
+converted to floating-point type, if necessary. If
+.meta dividend
+is omitted,
+then it is taken to be
+.code 1.0
+and the function calculates the reciprocal.
+
+The
+.code trunc
+function performs a division of
+.meta dividend
+by
+.meta divisor
+whose result
is truncated to integer toward zero. If both operands are integers, then an
integer division is performed and the result is an integer. If either operand
is a floating point value, a floating point division occurs, and the result is
truncated toward zero to a floating-point integral value.
-The mod function performs a modulus operation. Firstly, the absolute value
-of <divisor> is taken to be a modulus. Then a residue of <dividend>
-with respect to <modulus> is calculated. The residue's sign follows
-that of the sign of <divisor>. That is, it is the smallest magnitude
-(closest to zero) residue of <dividend> with respect to the absolute
-value of <divisor>, having the same sign as <divisor>.
+The
+.code mod
+function performs a modulus operation. Firstly, the absolute value
+of
+.meta divisor
+is taken to be a modulus. Then a residue of
+.meta dividend
+with respect to
+.meta modulus
+is calculated. The residue's sign follows
+that of the sign of
+.metn divisor .
+That is, it is the smallest magnitude
+(closest to zero) residue of
+.meta dividend
+with respect to the absolute
+value of
+.metn divisor ,
+having the same sign as
+.metn divisor .
If the operands are integer, the result is an integer. If either operand
is of type float, then the result is a float. The modulus operation is
-then generalized into the floating point domain. For instance the
-(mod 0.75 0.5) yields a residue of 0.25 because 0.5 "goes into" 0.75 only
+then generalized into the floating point domain. For instance the expression
+.code (mod 0.75 0.5)
+yields a residue of 0.25 because 0.5 "goes into" 0.75 only
once, with a "remainder" of 0.25.
-.SS Function gcd
-
-.TP
-Syntax:
-
- (gcd <left> <right>)
-
-.TP
-Description:
-
-The gcd function computes the greatest common divisor: the largest positive
+.coNP Function @ gcd
+.synb
+.mods (gcd < left << right )
+.syne
+.desc
+The
+.code gcd
+function computes the greatest common divisor: the largest positive
integer which divides both arguments.
-Operands <left> and <right> must be integers, or else an exception is thrown.
-
-The value of (gcd 0 x) is 0 for all x, including 0.
-
-The value of (gcd x 123) is is (abs x) for all x.
+Operands
+.meta left
+and
+.meta right
+must be integers, or else an exception is thrown.
+
+The value of
+.code (gcd 0 x)
+is 0 for all
+.codn x ,
+including 0.
+
+The value of
+.code (gcd x 123)
+is
+.code (abs x)
+for all
+.codn x .
Negative operands are permitted; this operation effectively ignores sign, so
-that the value of (gcd x y) is the same as (gcd (abs x) (abs y)) for all
-x and y.
-
-.SS Function abs
-
-.TP
-Syntax:
-
- (abs <number>)
-
-.TP
-Description:
-
-The abs function computes the absolute value of <number>. If <number>
-is positive, it is returned. If the number is negative, its additive inverse is
+that the value of
+.code (gcd x y)
+is the same as
+.code (gcd (abs x) (abs y))
+for all
+.code x
+and
+.codn y .
+
+.coNP Function @ abs
+.synb
+.mets (abs << number )
+.syne
+.desc
+The
+.code abs
+function computes the absolute value of
+.metn number .
+If
+.meta number
+is positive, it is returned. If
+.meta number
+is negative, its additive inverse is
returned: a positive number of the same type with exactly the same magnitude.
-.SS Functions floor, ceil
-
-.TP
-Syntax:
-
- (floor <number>)
- (ceil <number>)
-
-.TP
-Description:
-
-The floor function returns the highest integer which does not exceed
-the value of <number>. The ceiling function returns the lowest integer which
-does not exceed the value of <number>.
+.coNP Functions @ floor and @ ceil
+.synb
+.mets (floor << number )
+.mets (ceil << number )
+.syne
+.desc
+The
+.code floor
+function returns the highest integer which does not exceed
+the value of
+.metn number .
+The ceiling function returns the lowest integer which
+does not exceed the value of
+.metn number .
-If <number> an integer, it is simply returned.
+If
+.meta number
+an integer, it is simply returned.
If the argument is a float, then the value returned is a float.
-For instance (floor 1.1) returns 1.0 rather than 1.
-
-.SS Functions sin, cos, tan, asin, acos, atan, atan2
-
-.TP
-Syntax:
-
- (sin <radians>)
- (cos <radians>)
- (tan <radians>)
- (atan <slope>)
- (atan2 <y> <x>)
- (asin <num>)
- (acos <num>)
-
-.TP
-Description:
-
+For instance
+.code (floor 1.1)
+returns 1.0 rather than 1.
+
+.coNP Functions @, sin @, cos @, tan @, asin @, acos @ atan and @ atan2
+.synb
+.mets (sin << radians )
+.mets (cos << radians )
+.mets (tan << radians )
+.mets (atan << slope )
+.mets (atan2 < y << x )
+.mets (asin << num )
+.mets (acos << num )
+.syne
+.desc
These trigonometric functions convert their argument to floating point and
-return a float result. The sin, cos and tan functions compute the sine and
-cosine and tangent of the <radians> argument which represents an angle
-expressed in radians. The atan, acos and asin are their respective inverse
-functions. The <num> argument to asin and acos must be in the
-range -1.0 to 1.0. The atan2 function converts the rectilinear coordinates
-<x> and <y> to an angle in polar coordinates in the range [0, 2pi).
-
-.SS Functions exp, log, log10 and log2
-
-.TP
-Syntax:
-
- (exp <number>)
- (log <number>)
- (log10 <number>)
- (log2 <number>)
-
-.TP
-Description:
-
-The exp function calculates the value of the transcendental number e raised to
-the specified exponent.
-
-The log function calculates the base e logarithm of its argument, which must
-be a positive value.
-
-The log10 function calculates the base 10 logarithm of its argument, which must
-be a positive value.
-
-The log2 function calculates the base 2 logarithm of its argument, which must
-be a positive value.
-
-Integer arguments are converted to floats.
-
-.SS Functions expt, sqrt, isqrt
-
-.TP
-Syntax:
-
- (expt <base> <exponent>*)
- (sqrt <number>)
- (isqrt <integer>)
-
-.TP
-Description:
-
-The expt function raises <base> to zero or more exponents given
-by the <exponent> arguments.
-(expt x) is equivalent to (expt x 1); and yields x for all x.
-For three or more arguments, the operation is right associative.
-That is to say, (expt x y z) is equivalent to (expt x (expt y z)) and
-so forth, similarly to the way nested exponents work in standard algebraic
-notation.
+return a float result. The
+.codn sin ,
+.code cos
+and
+.code tan
+functions compute the sine and
+cosine and tangent of the
+.meta radians
+argument which represents an angle
+expressed in radians. The
+.codn atan ,
+.code acos
+and
+.code asin
+are their respective inverse
+functions. The
+.meta num
+argument to
+.code asin
+and
+.code acos
+must be in the
+range -1.0 to 1.0. The
+.code atan2
+function converts the rectilinear coordinates
+.meta x
+and
+.meta y
+to an angle in polar coordinates in the range [0, 2\(*p).
+
+.coNP Functions @, exp @, log @ log10 and @ log2
+.synb
+.mets (exp << arg )
+.mets (log << arg )
+.mets (log10 << arg )
+.mets (log2 << arg )
+.syne
+.desc
+The
+.code exp
+function calculates the value of the transcendental number e raised to
+the exponent
+.metn arg .
+
+The
+.code log
+function calculates the base e logarithm of
+.metn arg ,
+which must be a positive value.
+
+The
+.code log10
+function calculates the base 10 logarithm of
+.metn arg ,
+which must be a positive value.
+
+The
+.code log2
+function calculates the base 2 logarithm of
+.metn arg ,
+which must be a positive value.
+
+.coNP Functions @, expt @ sqrt and @ isqrt
+.synb
+.mets (expt < base << exponent *)
+.mets (sqrt << arg )
+.mets (isqrt << arg )
+.syne
+.desc
+The
+.code expt
+function raises
+.meta base
+to zero or more exponents given
+by the
+.meta exponent
+arguments.
+.code (expt x)
+is equivalent to
+.codn (expt x 1) ,
+and yields
+.code x
+for all
+.codn x .
+For three or more arguments, the operation is right-associative.
+That is to say,
+.code (expt x y z)
+is equivalent to
+.codn (expt x (expt y z)) ,
+similarly to the way nested exponents work in standard algebraic
+notation.
Exponentiation is done pairwise using a binary operation.
If both operands to this binary operation are integers, then the
@@ -11238,556 +17683,848 @@ operand is converted to a float, and a floating point exponentiation
is performed. Exponentiation that would produce a complex number is
not supported.
-The sqrt function produces a floating-point square root. The numeric
-operand is converted from integer to floating-point if necessary.
-Negative operands are not supported.
-
-The isqrt function computes an integer square root: a value which is the
-greatest integer that is no greater than the true square root of the input
-value. The input value must be an integer.
-
-.SS Function exptmod
-
-.TP
-Syntax:
-
- (exptmod <base> <exponent> <modulus>)
-
-.TP
-Description:
-
-The exptmod function performs modular exponentiation and accepts only integer
-arguments. Furthermore, <exponent> must be a non-negative and <modulus>
+The
+.code sqrt
+function produces a floating-point square root of
+.metn arg ,
+which is converted from integer to floating-point if necessary. Negative
+operands are not supported.
+
+The
+.code isqrt
+function computes the integer square root of
+.metn arg ,
+which must be an integer.
+The integer square root is a value which is the
+greatest integer that is no greater than the real square root of
+.metn arg .
+The input value must be an integer.
+
+.coNP Function @ exptmod
+.synb
+.mets (exptmod < base < exponent << modulus )
+.syne
+.desc
+The
+.code exptmod
+function performs modular exponentiation and accepts only integer
+arguments. Furthermore,
+.meta exponent
+must be a non-negative and
+.meta modulus
must be positive.
-The return value is <base> raised to <exponent>, and reduced to the
-least positive residue modulo <modulus>.
-
-.SS Function cum-norm-dist
-
-.TP
-Syntax:
-
- (cum-norm-dist <argument>)
-
-.TP
-Description:
-
-The cum-norm-dist function calculates an approximation to the cumulative normal
+The return value is
+.meta base
+raised to
+.metn exponent ,
+and reduced to the
+least positive residue modulo
+.metn modulus .
+
+.coNP Function @ cum-norm-dist
+.synb
+.mets (cum-norm-dist << argument )
+.syne
+.desc
+The
+.code cum-norm-dist
+function calculates an approximation to the cumulative normal
distribution function: the integral, of the normal distribution function, from
-negative infinity to the <argument>.
-
-.SS Functions n-choose-k and n-perm-k
-
-.TP
-Syntax:
-
- (n-choose-k <n> <k>)
- (n-perm-k <n> <k>)
-
-.TP
-Description:
-
-The n-choose-k function computes the binomial coefficient nCk which
-expresses the number of combinations of <k> items that can be chosen from
-a set of <n>, where combinations are subsets.
-
-The n-perm-k function computes nPk: the number of permutations of size <k>
-that can be drawn from a set of <n>, where permutations are sequences,
+negative infinity to the
+.metn argument .
+
+.coNP Functions @ n-choose-k and @ n-perm-k
+.synb
+.mets (n-choose-k < n << k )
+.mets (n-perm-k < n << k )
+.syne
+.desc
+The
+.code n-choose-k
+function computes the binomial coefficient nCk which
+expresses the number of combinations of
+.meta k
+items that can be chosen from
+a set of
+.metn n ,
+where combinations are subsets.
+
+The
+.code n-perm-k
+function computes nPk: the number of permutations of size
+.meta k
+that can be drawn from a set of
+.metn n ,
+where permutations are sequences,
whose order is significant.
-The calculations only make sense when <n> and <k> are nonnegative integers, and
-<k> does not exceed <n>. The behavior is not specified if these conditions
+The calculations only make sense when
+.meta n
+and
+.meta k
+are nonnegative integers, and
+.meta k
+does not exceed
+.metn n .
+The behavior is not specified if these conditions
are not met.
-.TP
-Description:
-
-The cum-norm-dist function calculates an approximation to the cumulative normal
-distribution function: the integral, of the normal distribution function, from
-negative infinity to the <argument>.
-
-
-.SS Functions fixnump, bignump, integerp, floatp, numberp
-
-.TP
-Syntax:
-
- (fixnump <object>)
- (bignump <object>)
- (integerp <object>)
- (floatp <object>)
- (numberp <object>)
-
-.TP
-Description:
-
-These functions test the type of <object>, returning true if it is an object
-of the implied type. The fixnump, bignump and floatp functions return true if
-the object is of the basic type fixnum, bignum or float.
-The function integerp returns true of <object> is either a fixnum or
-a bignum. The function numberp returns true if the object is either
-a fixnum, bignum or float.
-
-.SS Function zerop
-
-.TP
-Syntax:
-
- (zerop <number>)
-
-.TP
-Description:
-
-The zerop function tests <number> for equivalence to zero. The argument must be
-a number. It returns t for the integer value 0, and for the floating-point
-value 0.0. For other numbers, it returns nil.
-
-.SS Functions evenp, oddp
-
-.TP
-Syntax:
-
- (evenp <integer>)
- (oddp <integer>)
-
-.TP
-Description:
-
-The evenp and oddp functions require integer arguments. evenp returns
-t if <integer> is even (divisible by two), otherwise it returns nil.
-oddp returns t if <integer> is not divisible by two (odd), otherwise
-it returns nil.
-
-.SS Functions >, <, >=, <= and =
-
-.TP
-Syntax:
-
- (> <number> <number>*)
- (< <number> <number>*)
- (>= <number> <number>*)
- (<= <number> <number>*)
- (= <number> <number>*)
-
-.TP
-Description:
-
+.coNP Functions @, fixnump @, bignump @, integerp @ floatp and @ numberp
+.synb
+.mets (fixnump << object )
+.mets (bignump << object )
+.mets (integerp << object )
+.mets (floatp << object )
+.mets (numberp << object )
+.syne
+.desc
+These functions test the type of
+.metn object ,
+returning
+.code t
+if it is an object
+of the implied type,
+.code nil
+otherwise. The
+.codn fixnump ,
+.code bignump
+and
+.code floatp
+functions return
+.code t
+if the object is of the basic type
+.codn fixnum ,
+.code bignum
+or
+.codn float .
+The function
+.code integerp
+returns true of
+.meta object
+is either a
+.code fixnum
+or
+a
+.codn bignum .
+The function
+.code numberp
+returns
+.code t
+if
+.meta object
+is either
+a
+.codn fixnum ,
+.code bignum
+or
+.codn float .
+
+.coNP Function @ zerop
+.synb
+.mets (zerop << number )
+.syne
+.desc
+The
+.code zerop
+function tests
+.meta number
+for equivalence to zero. The argument must be
+a number. It returns
+.code t
+for the integer value
+.code 0
+and for the floating-point
+value
+.codn 0.0 .
+For other numbers, it returns
+.codn nil .
+
+.coNP Functions @ evenp and @ oddp
+.synb
+.mets (evenp << integer )
+.mets (oddp << integer )
+.syne
+.desc
+The
+.code evenp
+and
+.code oddp
+functions require integer arguments.
+.code evenp
+returns
+.code t
+if
+.meta integer
+is even (divisible by two), otherwise it returns
+.codn nil .
+.code oddp
+returns
+.code t
+if
+.meta integer
+is not divisible by two (odd), otherwise
+it returns
+.codn nil .
+
+.coNP Functions @, > @, < @, >= @ <= and @ =
+.synb
+.mets (> < number << number *)
+.mets (> < number << number *)
+.mets (>= < number << number *)
+.mets (<= < number << number *)
+.mets (= < number << number *)
+.syne
+.desc
These relational functions compare characters and numbers for numeric equality
or inequality. The arguments must be one or more numbers or characters.
-If just one argument is given, then these functions all return t.
+If just one argument is given, then these functions all return
+.codn t .
-If two arguments are given, then, they are compared as follows.
+If two arguments are given then, they are compared as follows.
First, if the numbers do not have the same type, then the one
which has the lower ranking type is converted to the type of
the other, according to this ranking: character < integer < float.
-For instance if a character and integer is compared, the character
+For instance if a character and integer are compared, the character
is converted to integer. Then a straightforward numeric comparison
is applied.
Three or more arguments may be given, in which case the comparison proceeds
-pairwise from left to right. For instance in (< a b c), the comparison (< a b)
-is performed in isolation. If it yields false, then nil is returned, otherwise
-the comparison (< b c) is performed in isolation, and if that yields false, nil
-is returned, otherwise t is returned. Note that it is possible for b to
-undergo two different conversions. For instance in (< <float> <character>
-<integer>), the character will convert to a floating-point representation of
-its Unicode, and if that comparison succeeds, then in the second comparison, the
-character will convert to integer.
-
-.SS Function /=
-
-.TP
-Syntax:
-
- (/= <number>*)
-
-.TP
-Description:
-
-The arguments to /= may be numbers or characters. The /= function returns t if
-no two of its arguments are numerically equal. That is to say, if there exist
-some a and b which are distinct arguments such that (= a b) is true, then
-the function returns nil. Otherwise it returns t.
-
-.SS Functions max and min
-
-.TP
-Syntax:
-
- (max <number> <number>*)
- (min <number> <number>*)
-
-.TP
-Description:
-
-The max and min functions determine and return the highest or lowest
+pairwise from left to right. For instance in
+.codn (< a b c) ,
+the comparison
+.code (< a b)
+is performed in isolation. If the comparison is false, then
+.code nil
+is returned, otherwise
+the comparison
+.code (< b c)
+is performed in isolation, and if that is false,
+.code nil
+is returned, otherwise
+.code t
+is returned. Note that it is possible for
+.code b
+to
+undergo two different conversions. For instance in the
+.cblk
+.meti (< < float < character << integer )
+.cble
+comparison,
+.meta character
+will first convert to a floating-point representation
+of its Unicode value so that it can be compared to
+.metn float ,
+and if that comparison succeeds, then in the second comparison,
+.meta character
+will be converted to integer so that it can be compared to
+.metn integer .
+
+.coNP Function @ /=
+.synb
+.mets (/= << number *)
+.syne
+.desc
+The arguments to
+.code /=
+may be numbers or characters. The
+.code /=
+function returns
+.code t
+if no two of its arguments are numerically equal. That is to say, if there
+exist some
+.code a
+and
+.code b
+which are distinct arguments such that
+.code (= a b)
+is true, then
+the function returns
+.codn nil .
+Otherwise it returns
+.codn t .
+
+.coNP Functions @ max and @ min
+.synb
+.mets (max < first-arg << arg *)
+.mets (min < first-arg << args *)
+.syne
+.desc
+The
+.code max
+and
+.code min
+functions determine and return the highest or lowest
value from among their arguments.
The arguments must be numbers or characters.
-If only a single argument is given, that value is returned.
-
-If two arguments are given, then (max a b) is equivalent to (if (>= a b) a b),
-and (min a b) is equivalent to (if (<= a b) a b). If the operands do not
+If only
+.meta first-arg
+is given, that value is returned.
+
+If two or more arguments are given, then
+.code (max a b)
+is equivalent to
+.codn (if (>= a b) a b) ,
+and
+.code (min a b)
+is equivalent to
+.codn (if (<= a b) a b) .
+If the operands do not
have the same type, then one of them is converted to the type of the other;
however, the original unconverted values are returned. For instance
-(max 4 3.0) yields the integer 4, not 4.0.
-
-If three or more arguments are given, max and min are left-associative.
-Thus (max a b c) is (max (max a b) c).
-
-.SS Functions int-str, flo-str and num-str
-
-.TP
-Syntax:
-
- (int-str <string> [<radix>])
- (flo-str <string>)
- (num-str <string>)
-
-.TP
-Description:
-
-These functions extract numbers <string>. Leading whitespace, if
-any, is skipped. If no digits can be successfully extracted, then nil is
-returned. Trailing material which does not contribute to the number
-is ignored.
-
-The int-str function converts a string of digits in the specified
+.code (max 4 3.0)
+yields the integer
+.codn 4 ,
+not
+.codn 4.0 .
+
+If three or more arguments are given,
+.code max
+and
+.code min
+reduce the arguments in a left-associative manner.
+Thus
+.code (max a b c)
+means
+.codn (max (max a b) c) .
+
+.coNP Functions @, int-str @ flo-str and @ num-str
+.synb
+.mets (int-str < string <> [ radix ])
+.mets (flo-str << string )
+.mets (num-str << string )
+.syne
+.desc
+These functions extract numeric values from character string
+.metn string .
+Leading whitespace in
+.metn string ,
+if any, is skipped. If no digits can be successfully extracted, then
+.code nil
+is returned. Trailing material which does not contribute to the number is
+ignored.
+
+The
+.code int-str
+function converts a string of digits in the specified
radix to an integer value. If the radix isn't specified, it defaults to 10.
For radices above 10, letters of the alphabet
-are used for digits: A represent a digit whose value is 10, B represents 11 and
-so forth until Z. For values of radix above 36, the returned value is
+are used for digits:
+.code A
+represent a digit whose value is 10,
+.code B
+represents 11 and
+so forth until
+.codn Z .
+For values of radix above 36, the returned value is
unspecified. Upper and lower case letters are recognized.
Any character which is not a digit of the specified radix is regarded
as the start of trailing junk at which the extraction of the digits stops.
-The flo-str function converts a floating-point decimal notation to a nearby
+The
+.code flo-str
+function converts a floating-point decimal notation to a nearby
floating point value. The material which contributes to the value
is the longest match for optional leading space, followed by a
mantissa which consists of an optional sign followed by a mixture of at least
one digit, and at most one decimal point, optionally followed by an exponent
-part denoted by the letter E or e, an optional sign and one or more optional
-exponent digits.
-
-The num-str function converts a decimal notation to either an integer as if by
-a radix 10 application of int-str, or to a floating point value as if by
-flo-str. The floating point interpretation is chosen if the possibly empty
+part denoted by the letter
+.code E
+or
+.codn e ,
+an optional sign and one or more optional exponent digits.
+
+The
+.code num-str
+function converts a decimal notation to either an integer as if by
+a radix 10 application of
+.codn int-str ,
+or to a floating point value as if by
+.codn flo-str .
+The floating point interpretation is chosen if the possibly empty
initial sequence of digits (following any whitespace and optional sign) is
-followed by a period, e or E.
-
-.SS Functions int-flo and flo-int
-
-.TP
-Syntax:
-
- (int-flo <float>)
- (flo-int <integer>)
-
-.TP
-Description:
-
+followed by a period, or by
+.code e
+or
+.codn E .
+
+.coNP Functions @ int-flo and @ flo-int
+.synb
+.mets (int-flo << float )
+.mets (flo-int << integer )
+.syne
+.desc
These functions perform numeric conversion between integer and floating point
-type. The int-flo function returns an integer by truncating toward zero.
-The flo-int function returns an exact floating point value corresponding to the
-integer argument, if possible, otherwise an approximation using a nearby
+type. The
+.code int-flo
+function returns an integer by truncating toward zero.
+The
+.code flo-int
+function returns an exact floating point value corresponding to
+.metn integer ,
+if possible, otherwise an approximation using a nearby
floating point value.
-.SS Functions tofloat and toint
-
-.TP
-Syntax:
-
- (tofloat <value>)
- (toint <value> [<radix>])
-
-.TP
-Description:
-
-These convenience functions convert a given value to a floating-point value or
-to an integer, respectively.
+.coNP Functions @ tofloat and @ toint
+.synb
+.mets (tofloat << value )
+.mets (toint < value <> [ radix ])
+.syne
+.desc
+These convenience functions convert
+.meta value
+to floating-point or integer, respectively.
If a floating-point value is passed into tofloat, or an integer value into
toint, then the value is simply returned.
-If <value> is a string, then it is converted by tofloat as if by the
-function flo-str, and by toint as if by the function int-str.
-
-If <value> is an integer, then it is converted by tofloat as if by
-the function flo-int.
-
-If <value> is a floating-point number, then it is converted by toint
-as if by the function int-flo.
-
-.SS Variables *flo-min*, *flo-max* and *flo-epsilon*
+If
+.meta value
+is a string, then it is converted by
+.code tofloat
+as if by the function
+.metn flo-str ,
+, and by
+.code toint
+as if by the function
+.codn int-str .
-.TP
-Description:
+If
+.meta value
+is an integer, then it is converted by
+.code tofloat
+as if by the function
+.codn flo-int .
+If
+.meta value
+is a floating-point number, then it is converted by
+.code toint
+as if by the function
+.codn int-flo .
+
+.coNP Variables @, *flo-min* @, *flo-max* and @ *flo-epsilon*
+.desc
These variables hold, respectively: the smallest positive floating-point
value; the largest positive floating-point value; and the difference
between 1.0 and the smallest representable value greater than 1.0.
-The *flo-min* and *flo-max* define the floating-point range, which consists
-of five regions: values from (- *flo-max*) to (- *flo-min*); the value
-0.0, and values from *flo-min* to *flo-max*.
-
-.SS Variable *flo-dig*
-
+.code *flo-min*
+and
+.code *flo-max*
+define the floating-point range, which consists
+of three regions: values from
+.code (- *flo-max*)
+to
+.codn (- *flo-min*) ;
+the value 0.0, and values from
+.code *flo-min*
+to
+.codn *flo-max* .
+
+.coNP Variable @ *flo-dig*
+.desc
This variable holds an integer representing the number of decimal digits
in a decimal floating-point number such that this number can be converted
to a TXR floating-point number, and back to decimal, without a change in any of
the digits. This holds regardless of the value of the number, provided that it
does not exceed the floating-point range.
-.TP
-Description:
-
-These variables hold, respectively: the smallest positive floating-point
-value; the largest positive floating-point value; and the difference
-between 1.0 and the smallest representable value greater than 1.0.
-
-.SS Variables *pi* and *e*
-
-.TP
-Description:
-
-These variables hold an approximation of the mathematical constants pi and e.
-To four digits of precision, pi is 3.142 and e is 2.718. The *pi* and *e*
-approximations are accurate to *flo-dig* decimal digits.
-
-.SH BIT OPERATIONS
-
+.coNP Variables *pi* and *e*
+.desc
+These variables hold an approximation of the mathematical constants \(*p and e.
+To four digits of precision, \(*p is 3.142 and e is 2.718. The
+.code *pi*
+and
+.code *e*
+approximations are accurate to
+.code *flo-dig*
+decimal digits.
+
+.SS* Bit Operations
In TXR Lisp, similarly to Common Lisp, bit operations on integers are based
-on "infinite two's-complement". That is to say, whereas a positive
-binary number can be regarded as being prefixed by an infinite stream of
-zero digits (for example 1 the same as 0001 or ...00001) a negative number
-in infinite two's complement can be conceptualized by an infinite prefix
-of 1 digits. So for instance the number -1 is represented by ...11111111: an
-infinite half-sequence of 1 digits. Any operation which produces such an
-infinite sequence gives rise to a negative number. For instance, consider the
-operation of computing the bitwise complement of the number 1. Since the
-number 1 is actually ...0000001, then the complement is ...11111110. Each
-one of the 0 digits in the infinite sequence is replaced by 1, giving rise
-to an infinite leading sequence of 1's. And this means that the number
-is negative, corresponding to the two's-complement representation of the
-value -2.
+on a concept that might be called "infinite two's-complement".
+Under infinite two's complement, a positive number is regarded as having
+a binary representation prefixed by an infinite stream of zero digits (for
+example
+.code 1
+is
+.codn ...00001 ).
+A negative number
+in infinite two's complement is the biwise negation of its positive counterpart,
+plus one: it carries an infinite prefix of 1 digits. So for instance the number
+.code -1
+is represented by
+.codn ...11111111 :
+an infinite sequence of
+1
+bits. There
+is no specific sign bit; any operation which produces such an infinite sequence
+of 1 digits on the left gives rise to a negative number. For instance, consider the
+operation of computing the bitwise complement of the number
+.codn 1 .
+Since the
+number
+.code 1
+is represented as
+.codn ...0000001 ,
+its complement is
+.codn ...11111110 .
+Each one of the
+.cod 0
+digits in the infinite sequence is replaced by
+.codn 1 ,
+And this leading sequence means that the number
+is negative, in fact corresponding to the two's-complement representation of
+the value
+.codn -2 .
+Hence, the infinite digit concept corresponds to an arithmetic
+interpretation.
In fact TXR Lisp's bignum integers do not use a two's complement
-representation. Numbers are represented as an array which holds a pure
-binary number. A separate field indicates the sign, positive or non-negative.
-That negative numbers appear as two's-complement under the bit operations
-is merely a carefully maintained illusion (which makes bit operations on
-negative numbers more expensive).
-
-The logtrunc function, and a feature of the lognot function, allows bit
+representation internally. Numbers are represented as an array which holds a
+pure binary number. A separate field indicates the sign, positive or
+non-negative. That negative numbers appear as two's-complement under the bit
+operations is merely a carefully maintained illusion (which makes bit
+operations on negative numbers more expensive).
+
+The
+.code logtrunc
+function, as well as a feature of the
+.code lognot
+function, allow bit
manipulation code to be written which works with positive numbers only, even if
-complements are required. The trade off is that the application has to manage
-a limit on the number of bits.
-
-.SS Functions logand, logior, logxor
-
-.TP
-Syntax:
-
- (logand <integer>*)
- (logior <integer>*)
- (logxor <int1> <int2>)
-
-.TP
-Description:
-
+complements are required. The trade off is that the application has to manage a
+limit on the number of bits.
+
+.coNP Functions @, logand @, logior and @ logxor
+.synb
+.mets (logand << integer *)
+.mets (logior << integer *)
+.mets (logxor < int1 << int2 )
+.syne
+.desc
These operations perform the familiar bitwise and, inclusive or, and exclusive
-or operations respectively. Positive values inputs are treated as
+or operations, respectively. Positive values inputs are treated as
pure binary numbers. Negative inputs are treated as infinite-bit
two's-complement.
-For example (logand -2 7) produces 6. This is because -2 is ..111110 in
-infinite-bit two's-complement. Or-ing this value with 7 (111) produces
-110.
-
-The logand and logior functions are variadic, and may be called with zero, one,
-two, or more input values. If logand is called with no arguments, it produces
-the value -1 (all bits 1). If logior is called with no arguments it produces
+For example
+.code (logand -2 7)
+produces
+.codn 6 .
+This is because
+.code -2
+is
+.code ...111110
+in infinite-bit two's-complement. And-ing this value with
+.code 7
+(or
+.codn ...000111 )
+produces
+.codn 110 .
+
+The
+.code logand
+and
+.code logior
+functions are variadic, and may be called with zero, one,
+two, or more input values. If
+.code logand
+is called with no arguments, it produces
+the value -1 (all bits 1). If
+.code logior
+is called with no arguments it produces
zero. In the one-argument case, the functions just return their argument value.
-
-
-.SS Functions logtest
-
-.TP
-Syntax:
-
- (logtest <int1> <int2>)
-
-.TP
-Description:
-
-The logtest function returns true if <int1> and <int1> have bits in
+.coNP Function @ logtest
+.synb
+.mets (logtest < int1 << int2 )
+.syne
+.desc
+The
+.code logtest
+function returns true if
+.meta int1
+and
+.meta int2
+have bits in
common. The following equivalence holds:
+.cblk
(logtest a b) <--> (not (zerop (logand a b)))
-
-.SS Functions lognot and logtrunc
-
-.TP
-Syntax:
-
- (lognot <value> [<bits>])
- (logtrunc <value> <bits>)
-
-.TP
-Description:
-
-The lognot function performs a bitwise complement of <value>.
-When the one-argument form of lognot is used, then if <value> is nonnegative,
+.cble
+
+.coNP Functions @ lognot and @ logtrunc
+.synb
+.mets (lognot > value <> [ bits ])
+.mets (logtrunc > value << bits )
+.syne
+.desc
+The
+.code lognot
+function performs a bitwise complement of
+.metn value .
+When the one-argument form of lognot is used, then if
+.meta value
+is nonnegative,
then the result is negative, and vice versa, according to the infinite-bit
-two's complement representation. For instance (lognot -2) is 1,
-and (lognot 1) is -2.
-
-The two-argument form of lognot produces a truncated complement. Conceptually,
-t a bitwise complement is first calculated, and then the resulting number is
-truncated to the number of bits given by <bits>, which must be a nonnegative
-integer. The following equivalence holds:
-
+two's complement representation. For instance
+.code (lognot -2)
+is
+.codn 1 ,
+and
+.code (lognot 1)
+is
+.codn -2 .
+
+The two-argument form of
+.code lognot
+produces a truncated complement. Conceptually,
+a bitwise complement is first calculated, and then the resulting number is
+truncated to the number of bits given by
+.metn bits ,
+which must be a nonnegative integer. The following equivalence holds:
+
+.cblk
(lognot a b) <--> (logtrunc (lognot a) b)
-
-The logtrunc function truncates the integer <value> to the specified number
-of bits. If <value> is negative, then the two's-complement representation
-is truncated. The return value of logtrunc is always a non-negative integer.
-
-.SS Function ash
-
-.TP
-Syntax:
-
- (ash <value> <bits>)
-
-.TP
-Description:
-
-The ash function shifts <value> by the specified number of <bits> producing a
-new value. If <bits> is positive, then a left shift takes place. If <bits>
-is negative, then a right shift takes place. If <bits> is zero, then
-<value> is returned unaltered. For positive numbers, a left shift by n bits is
-equivalent to a multiplication by two to the power of n, or (expt 2 n).
+.cble
+
+The
+.code logtrunc
+function truncates the integer
+.meta value
+to the specified number
+of bits. If
+.meta value
+is negative, then the two's-complement representation
+is truncated. The return value of
+.code logtrunc
+is always a non-negative integer.
+
+.coNP Function @ ash
+.synb
+.mets (ash < value << bits )
+.syne
+.desc
+The
+.code ash
+function shifts
+.meta value
+by the specified number of
+.meta bits
+producing a
+new value. If
+.meta bits
+is positive, then a left shift takes place. If
+.meta bits
+is negative, then a right shift takes place. If
+.meta bit
+is zero, then
+.meta value
+is returned unaltered. For positive numbers, a left shift by n bits is
+equivalent to a multiplication by two to the power of n, or
+.codn (expt 2 n) .
A right shift by n bits of a positive integer is equivalent to integer
-division by (expt 2 n), with truncation toward zero.
+division by
+.codn (expt 2 n) ,
+with truncation toward zero.
For negative numbers, the bit shift is performed as if on the two's-complement
representation. Under the infinite two's-complement representation,
-a right shift does not exhaust the infinite sequence of 1 digits which
-extends to the left. Thus if -4 is shifted right it becomes -2 because
-the bitwise representations are ...111100 and ...11110.
-
-.SS Function bit
-
-.TP
-Syntax:
-
- (bit <value> <bit>)
-
-.TP
-Description:
-
-The bit function tests whether the integer <value> has a 1 in bit position <bit>.
-The <bit> argument must be a non-negative integer. A value of zero of <bit>
-indicates the least significant bit position of <value>.
-
-The bit function has a boolean result, returning the symbol t if bit <bit>
-of <value> is set, otherwise nil.
-
-If <value> is negative, it is treated as if it had an infinite-bit two's
-complement representation. For instance, if value is -2, then the bit
-function returns nil for a <bit> value of zero, and t for all other values,
-since the infinite bit two's complement representation of -2 is ...11110.
-
-.SS Function mask
-
-.TP
-Syntax:
-
- (mask <integer>*)
-
-.TP
-Description:
+a right shift does not exhaust the infinite sequence of
+.code 1
+digits which
+extends to the left. Thus if
+.code -4
+is shifted right it becomes
+.code -2
+because
+the bitwise representations of these values are
+.code ...111100
+and
+.codn ...11110 .
+
+.coNP Function @ bit
+.synb
+.mets (bit < value << bit )
+.syne
+.desc
+The
+.code bit
+function tests whether the integer
+.meta value
+has a 1 in bit position
+.metn bit .
+The
+.meta bit
+argument must be a non-negative integer. A value of zero of
+.meta bit
+indicates the least significant bit position of
+.metn value .
+
+The
+.code bit
+function has a boolean result, returning the symbol
+.code t
+if bit
+.meta bit
+of
+.meta value
+is set, otherwise
+.codn nil .
-The mask function takes zero or more integer arguments, and produces an integer
+If
+.meta value
+is negative, it is treated as if it had an infinite-bit two's
+complement representation. For instance, if value is
+.codn -2 ,
+then the bit
+function returns
+.code nil
+for a
+.meta bit
+value of zero, and
+.code t
+for all other values,
+since the infinite bit two's complement representation of
+.code -2
+is
+.codn ...11110 .
+
+.coNP Function @ mask
+.synb
+.mets (mask << integer *)
+.syne
+.desc
+The
+.code mask
+function takes zero or more integer arguments, and produces an integer
value which corresponds a bitmask made up of the bit positions specified by the
integer values.
-If mask is called with no arguments, then the return value is zero.
+If
+.code mask
+is called with no arguments, then the return value is zero.
-If mask is called with a single argument B then the return value is the same as
-that of the expression (ash 1 <value>): one shifted left by <value> bit
-positions. If <value> is zero, then the result is 1; if <value> is 1, the
-result is 2 and so forth. If <value> is negative, then the result is zero.
+If
+.code mask
+is called with a single argument
+.meta integer
+then the return value is the same as
+that of the expression
+.codn (ash 1 <integer>) :
+the value 1 shifted left by
+.meta integer
+bit positions. If
+.meta integer
+is zero, then the result is
+.codn 1 ;
+if
+.meta integer
+is
+.codn 1 ,
+the
+result is
+.code 2
+and so forth. If
+.meta value
+is negative, then the result is zero.
-If mask is called with two or more arguments, then the result is a bitwise of
-the masks individually computed for each of the values.
+If
+.code mask
+is called with two or more arguments, then the result is a bitwise of
+the masks individually computed for each of the values.
In other words, the following equivalences hold:
- (mask) == 0
- (mask a) == (ash 1 a)
- (mask a b c ...) == (logior (mask a) (mask b) (mask c) ...)
-
-.SH EXCEPTIONS
-
-.SS Functions throw, throwf and error
-
-.TP
-Syntax:
-
- (throw <symbol> <arg>*)
- (throwf <symbol> <format-string> <format-arg>*)
- (error <format-string> <format-arg>*)
-
-.TP
-Description:
-
-These functions generate an exception. The throw and throwf functions generate
-an exception identified by <symbol>, whereas error throws an exception of
-type error. The call (error ...) can be regarded as a shorthand for
-(throwf 'error ...).
-
-The throw function takes zero or more additional arguments. These arguments
-become the arguments of a catch handler which takes the exception. The
+.cblk
+ (mask) <--> 0
+ (mask a) <--> (ash 1 a)
+ (mask a b c ...) <--> (logior (mask a) (mask b) (mask c) ...)
+.cble
+
+.SS* Exceptions
+.coNP Functions @, throw @ throwf and @ error
+.synb
+.mets (throw < symbol << arg *)
+.mets (throwf < symbol < format-string << format-arg *)
+.mets (error < format-string << format-arg *)
+.syne
+.desc
+These functions generate an exception. The
+.code throw
+and
+.code throwf
+functions generate
+an exception identified by
+.metn symbol ,
+whereas
+.code error
+throws an exception of
+type
+.codn error .
+The call
+.code (error ...)
+can be regarded as a shorthand for
+.codn (throwf 'error ...) .
+
+The
+.code throw
+function takes zero or more additional arguments. These arguments
+become the arguments of a
+.code catch
+handler which takes the exception. The
handler will have to be capable of accepting that number of arguments.
-The throwf and error functions generate an exception which has a single
+The
+.code throwf
+and
+.code error
+functions generate an exception which has a single
argument: a character string created by a formatted print to a string stream
-using the format string and additional arguments.
-
-.SS Operator catch
-
-.TP
-Syntax:
-
- (catch <try-expression>
- {(<symbol> (<arg>*) <body-form>*)}*)
-
-.TP
-Description:
-
-The catch operator establishes an exception catching block around
-the <try-expression>. The <try-expression> is followed by zero or more
+using the
+.code format
+string and additional arguments.
+
+.coNP Operator @ catch
+.synb
+.mets (catch < try-expression
+.mets \ \ >> {( symbol <> ( arg *) << body-form *)}*)
+.syne
+.desc
+The
+.code catch
+operator establishes an exception catching block around
+the
+.metan try-expression .
+The
+.meta try-expression
+is followed by zero or more
catch clauses. Each catch clause consists of a symbol which denotes
an exception type, an argument list, and zero or more body forms.
-If <try-expression> terminates normally, then the catch clauses
+If
+.meta try-expression
+terminates normally, then the catch clauses
are ignored. The catch itself terminates, and its return value is
-that of the <try-expression>.
+that of the
+.metn try-expression .
-If <try-expression> throws an exception which is a subtype of one or more of
+If
+.meta try-expression
+throws an exception which is a subtype of one or more of
the type symbols given in the exception clauses, then the first (leftmost) such
clause becomes the exit point where the exception is handled.
The exception is converted into arguments for the clause, and the clause
body is executed. When the clause body terminates, the catch terminates,
and the return value of the catch is that of the clause body.
-If <try-expression> throws an exception which is not a subtype of any of
+If
+.meta try-expression
+throws an exception which is not a subtype of any of
the symbols given in the clauses, then the search for an exit point for
the exception continues through the enclosing forms. The catch clauses
are not involved in the handling of that exception.
@@ -11795,85 +18532,138 @@ are not involved in the handling of that exception.
When a clause catches an exception, the number of arguments in the catch must
match the number of elements in the exception. A catch argument list
resembles a function or lambda argument list, and may be dotted. For instance
-the clause (foo (a . b)) catches an exception subtyped from foo, with one or
-more elements. The first element binds to parameter a, and the rest, if any,
-bind to parameter b. If there is only one element, b takes on the value nil.
-
-Also see: the unwind-protect operator, and the functions throw, throwf
-and error.
-
-.SH REGULAR EXPRESSION LIBRARY
-
-.SS Functions search-regex and range-regex
-
-.TP
-Syntax:
-
- (search-regex <haystack-string> <needle-regex> [ <start> [<from-end>] ])
- (range-regex <haystack-string> <needle-regex> [ <start> [<from-end>] ])
-
-.TP
-Description
-
-The search-regex function searches through <haystack-string> starting
-at position <start> for a match for <needle-regex>. If <start> is omitted,
-the search starts at position 0. If <from-end> is specified, the search
-proceeds in reverse, from the last position in the string, toward <start>.
-This function returns nil if no match is found, otherwise it returns
-a cons pair, whose car indicates the position of the match, and whose
-cdr indicates the length of the match.
-
-The range-regex function is similar to search-regex, except when
+the clause
+.code (foo (a . b))
+catches an exception subtyped from
+.codn foo ,
+with one or
+more elements. The first element binds to parameter
+.codn a ,
+and the rest, if any,
+bind to parameter
+.codn b .
+If there is only one element,
+.code b
+takes on the value
+.codn nil .
+
+Also see: the
+.code unwind-protect
+operator, and the functions
+.codn throw ,
+.code throwf
+and
+.codn error .
+
+.SS* Regular Expression Library
+.coNP Functions @ search-regex and @ range-regex
+.synb
+.mets (search-regex < string < regex >> [ start <> [ from-end ]])
+.mets (range-regex < string < regex >> [ start <> [ from-end ]])
+.syne
+.desc
+The
+.code search-regex
+function searches through
+.meta string
+starting
+at position
+.meta start
+for a match for
+.metn regex .
+If
+.meta start
+is omitted, the search starts at position 0. If
+.meta from-end
+is specified and has a
+.cod2 non- nil
+value, the search
+proceeds in reverse, from the last position in the string, toward
+.metn start .
+This function returns
+.code nil
+if no match is found, otherwise it returns
+a cons, whose
+.code car
+indicates the position of the match, and whose
+.code cdr
+indicates the length of the match.
+
+The
+.code range-regex
+function is similar to
+.codn search-regex ,
+except that when
a match is found, it returns a position range, rather than a position
-and length. A cons pair is returned whose car indicates the position
-of the match, and whose cdr indicates the position one element past the
+and length. A cons is returned whose
+.code car
+indicates the position
+of the match, and whose
+.code cdr
+indicates the position one element past the
last character of the match. If the match is empty, the two integers
are equal.
-.SS Function match-regex
-
-.TP
-Syntax:
-
- (match-regex <string> <regex> [<position>])
-
-.TP
-Description
-
-The match-regex function tests whether <regex> matches at <position>
-in <string>. If <position> is not specified, it is taken to be zero.
+.coNP Function @ match-regex
+.synb
+.mets (match-regex < string < regex <> [ position ])
+.syne
+.desc
+The
+.code match-regex
+function tests whether
+.meta regex
+matches at
+.meta position
+in
+.metn string .
+If
+.meta position
+is not specified, it is taken to be zero.
If the regex matches, then the length of the match is returned.
-If it does not match, then nil is returned.
-
-.SS Function match-regex-right
-
-.TP
-Syntax:
-
- (match-regex-right <string> <regex> [<end-position>])
-
-.TP
-Description
+If it does not match, then
+.code nil
+is returned.
-The match-regex function tests whether <string> contains a match which ends
-precisely on the character just before <end-position>. If <end-position> is
-not specified, it defaults to the length of the string, and the function
+.coNP Function @ match-regex-right
+.synb
+.mets (match-regex-right < string < regex <> [ end-position ])
+.syne
+.desc
+The
+.code match-regex
+function tests whether
+.meta string
+contains a match which ends
+precisely on the character just before
+.metn end-position .
+If
+.meta end-position
+is not specified, it defaults to the length of the string, and the function
performs a right-anchored regex match.
If a match is found, then the length of the match is returned, and
the matching substring is then returned.
-The match must terminate just before <end-position> in the sense that
-additional characters at <end-position> and beyond can no longer satisfy the
+The match must terminate just before
+.meta end-position
+in the sense that
+additional characters at
+.meta end-position
+and beyond can no longer satisfy the
regular expression. More formally, the function searches, starting from
position zero, for positions where there occurs a match for the regular
expression, taking the longest possible match. The length of first such a match
-which terminates on the character just before <end-position> is returned.
-If no such a match is found, then nil is returned.
+which terminates on the character just before
+.meta end-position
+is returned.
+If no such a match is found, then
+.code nil
+is returned.
-.TP
-Examples:
+.TP* Examples:
+.cblk
;; Return matching portion rather than length thereof.
(defun match-regex-right-substring (str reg : end-pos)
@@ -11882,7 +18672,7 @@ Examples:
(if len
[str (- end-pos len)..end-pos]
nil)))
-
+
(match-regex-right-substring "abc" #/c/) -> ""
(match-regex-right-substring "acc" #/c*/) -> "cc"
@@ -11898,84 +18688,112 @@ Examples:
;; Equivalent of above call
(match-regex-right-substring "ac" #/c*/) -> "c"
-
-
-.SS Function regsub
-
-.TP
-Syntax:
-
- (regsub <regex> <replacement> <string>)
-
-.TP
-Description:
-
-The regsub function searches <string> for multiple occurrences of
-non-overlapping matches for <regex>. A new string is constructed
-similar to <string> but in which each matching region is replaced
-with using <replacement> as follows.
-
-The <replacement> object may be a character or a string, in which
+.cble
+
+.coNP Function @ regsub
+.synb
+.mets (regsub < regex < replacement << string )
+.syne
+.desc
+The
+.code regsub
+function searches
+.meta
+string
+for multiple occurrences of
+non-overlapping matches for
+.metn regex .
+A new string is constructed
+similar to
+.meta string
+but in which each matching region is replaced
+with using
+.meta replacement
+as follows.
+
+The
+.meta replacement
+object may be a character or a string, in which
case it is simply taken to be the replacement for each match
of the regular expression.
-The <replacement> object may be a function of one argument, in
+The
+.meta replacement
+object may be a function of one argument, in
which case for every match which is found, this function is invoked,
with the matching piece of text as an argument. The function's
return value is then taken to be the replacement text.
-.TP
-Examples:
+.TP* Examples:
+.cblk
;; match every lower case e or o, and replace by filtering
;; through the upcase-str function:
-
+
[regsub #/[eo]/ upcase-str "Hello world!"] -> "HEllO wOrld!"
;; Replace Hello with Goodbye:
(regsub #/Hello/ "Goodbye" "Hello world!") -> "Goodbye world!"
-
-.SS Function regexp
-
-.TP
-Syntax:
-
- (regexp <obj>)
-
-.TP
-Description:
-
-The regexp function returns t if <obj> is a compiled regular expression
-object. For any other object type, it returns nil.
-
-.SS Function regex-compile
-
-.TP
-Syntax:
-
- (regex-compile <form-or-string> [<error-stream>])
-
-.TP
-Description:
-
-The regex compile function takes the source code of a regular expression,
+.cble
+
+.coNP Function @ regexp
+.synb
+.mets (regexp << obj )
+.syne
+.desc
+The
+.code regexp
+function returns
+.code t
+if
+.meta obj
+is a compiled regular expression
+object. For any other object type, it returns
+.codn nil .
+
+.coNP Function @ regex-compile
+.synb
+.mets (regex-compile < form-or-string <> [ error-stream ])
+.syne
+.desc
+The
+.code regex-compile
+function takes the source code of a regular expression,
expressed as a Lisp data structure representing an abstract syntax tree, or
else a regular expression specified as a character string, and compiles it to a
regular expression object.
-If <form-or-string> is a character string, it is parsed to an
-abstract syntax tree first, if by a call to (regex-parse <form-or-string>).
-If the parse is successful (the result is not nil) then
-it is compiled by a recursive call to regex-compile.
-
-The optional <error-stream> argument is passed down to regex-compile,
+If
+.meta form-or-string
+is a character string, it is parsed to an
+abstract syntax tree first, if by the
+.code regex-parse
+function.
+If the parse is successful (the result is not
+.codn nil )
+then
+the resulting tree structure is compiled by a recursive call to
+.codn regex-compile .
+
+The optional
+.meta error-stream
+argument is passed down to
+.code regex-parse
+as well as in the recursive call to
+.codn regex-compile ,
if that call takes place.
-.TP
-Examples:
+If
+.meta error-stream
+is specified, it must be a stream. Any error diagnostics are sent to that
+stream.
+
+.TP* Examples:
+.cblk
;; the equivalent of #/[a-zA-Z0-9_/
- (regex-compile '(set (#\ea . #\ez) (#\eA . #\eZ) (#\e0 . #\e9) #\e_))
+ (regex-compile '(set (#\ea . #\ez) (#\eA . #\eZ)
+ (#\e0 . #\e9) #\e_))
;; the equivalent of #/.*/ and #/.+/
(regex-compile '(0+ wild))
@@ -11986,49 +18804,58 @@ Examples:
;; string
(regex-compile "a|b|c")
-
-.SS Function regex-parse
-
-.TP
-Syntax:
-
- (regex-parse <string> [<error-stream>])
-
-.TP
-Description:
-
-The regex string parses a character string which contains a regular expression
+.cble
+
+.coNP Function @ regex-parse
+.synb
+.mets (regex-parse < string <> [ error-stream ])
+.syne
+.desc
+The
+.code regex-parse
+function parses a character string which contains a regular expression
(without any surrounding / characters) and turns it into a Lisp data structure
(the abstract syntax tree representation of the regular expression).
-The regular expression syntax #/RE/ produces the same structure, but as a
-literal which is processed at the time TXR source code is read; the regex-parse
+The regular expression syntax
+.code #/RE/
+produces the same structure, but as a
+literal which is processed at the time TXR source code is read; the
+.code regex-parse
function performs this parsing at run-time.
-If there are parse errors, the function returns nil.
-
-The optional <error-stream> argument specifies a stream to which error messages
-are sent from the parser. By default, diagnostic output goes to the *stdnull*
-stream, which discards it. If <error-stream> is specified as t, then the
-diagnostic output goes to the *stdout* stream.
-
-If regex-parse returns a non-nil value, that structure is then something
-which is suitable as input to regex-compile.
-
-.SH HASHING LIBRARY
-
-.SS Functions make-hash, hash
-
-.TP
-Syntax:
-
- (make-hash <weak-keys> <weak-vals> <equal-based>)
- (hash { :weak-keys | :weak-vals | :equal-based }*)
-
-.TP
-Description:
+If there are parse errors, the function returns
+.codn nil .
+
+The optional
+.meta error-stream
+argument specifies a stream to which error messages
+are sent from the parser. By default, diagnostic output goes to the
+.code *stdnull*
+stream, which discards it. If
+.meta error-stream
+is specified as
+.codn t ,
+then the diagnostic output goes to the
+.code *stdout*
+stream.
-These functions construct a new hash table, using different syntax.
+If
+.code regex-parse
+returns a
+.cod2 non- nil
+value, that structure is then something
+which is suitable as input to
+.codn regex-compile .
+
+.SS* Hashing Library
+.coNP Functions @, make-hash and @ hash
+.synb
+.mets (make-hash < weak-keys < weak-vals << equal-based )
+.mets (hash { :weak-keys | :weak-vals | :equal-based }*)
+.syne
+.desc
+These functions construct a new hash table.
A hash table is an object which retains an association between pairs of
objects. Each pair consists of a key and value. Given an object which is
@@ -12038,22 +18865,33 @@ lookup is facilitated by hashing: quickly mapping a key object to a numeric
value which is then used to index into one of many buckets where the matching
key will be found (if such a key is present in the hash table).
-make-hash takes three mandatory boolean arguments. The <weak-keys>
-argument specifies, whether the hash table shall have weak keys. The <weak-vals>
+.code make-hash
+takes three mandatory boolean arguments. The
+.meta weak-keys
+argument specifies whether the hash table shall have weak keys. The
+.meta weak-vals
argument specifies whether it shall have weak values, and
-<equal-based> specifies whether it is equal-based. The hash function defaults
+.meta equal-based
+specifies whether it is
+.codn equal- based.
+The hash function defaults
all three of these properties to false, and allows them to be overridden to
true by the presence of keyword arguments.
-It is an error to attempt to construct an equal-based hash table which
-has weak keys.
+It is an error to attempt to construct an
+.codn equal -based
+hash table which has weak keys.
The hash function provides an alternative interface. It accepts optional
arguments which are keyword symbols. Any combination of the three symbols
-:weak-keys, :weak-vals and :equal-based can be specified in any order
+.codn :weak-keys ,
+.code :weak-vals
+and
+.code :equal-based
+can be specified in any order
to turn on the corresponding properties in the newly constructed hash table.
If any of the keywords is not specified, the corresponding property defaults to
-nil.
+.codn nil .
If a hash table has weak keys, this means that from the point of view
of garbage collection, that table holds only weak references to the keys
@@ -12070,450 +18908,717 @@ hash table.
Important to the operation of a hash table is the criterion by which keys are
considered same. By default, this similarity follows the eql function. A hash
-table will search for a stored key which is eql to the given search key.
-A hash table constructed with the equal-based property compares keys using
-the equal function instead.
+table will search for a stored key which is
+.code eql
+to the given search key.
+A hash table constructed with the
+.codn equal -based
+property compares keys using
+the
+.code equal
+function instead.
In addition to storing key-value pairs, a hash table can have a piece of
information associated with it, called the user data.
-.SS Function hash-construct
-
-.TP
-Syntax:
-
- (hash-construct <hash-args> <key-val-pairs>)
-
-.TP
-Description:
-
-The hash-construct function constructs a populated hash in one step. The <hash-args>
-argument specifies a list suitable as an argument list in a call to the hash function.
-The <key-val-pairs> is a sequence of pairs, which are two-element lists representing
-key-value pairs.
-
-A hash is constructed as if by a call to [apply hash <hash-args>], then populated
+.coNP Function @ hash-construct
+.synb
+.mets (hash-construct < hash-args << key-val-pairs )
+.syne
+.desc
+The
+.code hash-construct
+function constructs a populated hash in one step. The
+.meta hash-args
+argument specifies a list suitable as an argument list in a call to the hash
+function. The
+.meta key-val-pairs
+is a sequence of pairs, which are two-element
+lists representing key-value pairs.
+
+A hash is constructed as if by a call to
+.cblk
+.meti [apply hash << hash-args ],
+.cble
+then populated
with the specified pairs, and returned.
-.SS Function hash-update
-
-.TP
-Syntax:
-
- (hash-update <hash> <function>)
-
-.TP
-Description:
-
-The hash-update function replaces each values in <hash>, with the value of
-<function> applied to that value.
-
-The return value is <hash>.
-
-.SS Function hash-update-1
+.coNP Function @ hash-update
+.synb
+.mets (hash-update < hash << function )
+.syne
+.desc
+The
+.code hash-update
+function replaces each values in
+.metn hash ,
+with the value of
+.meta function
+applied to that value.
+
+The return value is
+.metn hash .
+
+.coNP Function @ hash-update-1
+.synb
+.mets (hash-update-1 < hash < key < function <> [ init ])
+.syne
+.desc
+The
+.code hash-update-1
+function operates on a single entry in the hash table.
-.TP
-Syntax:
-
- (hash-update-1 <hash> <key> <function> [<init>])
-
-.TP
-Description:
-
-The hash-update-1 function operates on a single entry in the hash table.
-
-If <key> exists in the hash table, then its corresponding value is passed
-into <function>, and the return value of <function> is then installed
+If
+.meta key
+exists in the hash table, then its corresponding value is passed
+into
+.metn function ,
+and the return value of
+.meta function
+is then installed
in place of the key's value. The value is then returned.
-If <key> does not exist in the hash table, and no <init> argument is given,
-then the function does nothing and returns nil.
+If
+.meta key
+does not exist in the hash table, and no
+.meta init
+argument is given,
+then
+.code hash-update-1
+does nothing and returns
+.codn nil .
-If <key> does not exist in the hash table, and an <init> argument is given,
-then <function> is applied to <init>, and then <key> is inserted into
-<hash> with the value returned by <function> as the datum. This value
+If
+.meta key
+does not exist in the hash table, and an
+.meta init
+argument is given,
+then
+.meta function
+is applied to
+.metn init ,
+and then
+.meta key
+is inserted into
+.meta hash
+with the value returned by
+.meta function
+as the datum. This value
is also returned.
-.SS Function group-by
-
-.TP
-Syntax:
-
- (group-by <func> <sequence> <option>*)
-
-.TP
-Description:
-
-The group-by function produces a hash table from <sequence>, which is a
-list or vector. Entries of the hash table are not elements of sequence,
-but lists of elements of <sequence>. The function <func> is applied to
-each element of <sequence> to compute a key. That key is used to determine
+.coNP Function @ group-by
+.synb
+.mets (group-by < func < sequence << option *)
+.syne
+.desc
+The
+.code group-by
+function produces a hash table from
+.metn sequence ,
+which is a
+list or vector. Entries of the hash table are not elements of
+.metn sequence ,
+but lists of elements of
+.metn sequence .
+The function
+.meta func
+is applied to
+each element of
+.meta sequence
+to compute a key. That key is used to determine
which list the item is added to in the hash table.
-The trailing arguments <option>*, if any, consist of the same keywords
+The trailing arguments
+.cblk
+.meti << option *
+.cble
+if any, consist of the same keywords
that are understood by the hash function, and determine the properties
of the hash.
-.TP
-Example:
-
+.TP* Example:
Group the integers from 0 to 10 into three buckets keyed on 0, 1 and 2
according to the modulo 3 congruence:
+.cblk
(group-by (op mod @1 3) (range 0 10)))
-> #H(() (0 (0 3 6 9)) (1 (1 4 7 10)) (2 (2 5 8)))
-
-
-.SS Functions make-similar-hash and copy-hash
-
-.TP
-Syntax:
-
- (make-similar-hash <hash>)
- (copy-hash <hash>)
-
-.TP
-Description:
-
-The make-similar-hash and copy-hash functions create a new hash object based on
-the existing <hash> object.
-
-The make-similar-hash produces an empty hash table which inherits all of the
-attributes of <hash>. It uses the same kind of key equality, the
+.cble
+
+.coNP Functions @ make-similar-hash and @ copy-hash
+.synb
+.mets (make-similar-hash << hash )
+.mets (copy-hash << hash )
+.syne
+.desc
+The
+.code make-similar-hash
+and copy-hash functions create a new hash object based on
+the existing
+.meta hash
+object.
+
+.code make-similar-hash
+produces an empty hash table which inherits all of the
+attributes of
+.metn hash .
+It uses the same kind of key equality, the
same configuration of weak keys and values, and has the same user data (see
-the set-hash-userdata function).
-
-The copy-hash function is like make-similar-hash, except that instead of
+the
+.code set-hash-userdata
+function).
+
+The
+.code copy-hash
+function is like
+.codn make-similar-hash ,
+except that instead of
producing an empty hash table, it produces one which has all the same elements
-as <hash>: it contains the same key and value objects.
-
-.SS Function inhash
-
-.TP
-Syntax:
-
- (inhash <hash> <key> [<init>])
-
-.TP
-Description:
-
-The inhash function searches hash table <hash> for <key>.
-If <key> is found, then it return the hash table's cons cell which
-represents the association between <hash> and <key>.
-Otherwise, it returns nil.
-
-If argument <init> is specified, then the function will create
-an entry for <key> in <hash> whose value is that of <init>.
+as
+.metn hash :
+it contains the same key and value objects.
+
+.coNP Function @ inhash
+.synb
+.mets (inhash < hash < key <> [ init ])
+.syne
+.desc
+The
+.code inhash
+function searches hash table
+.meta hash
+for
+.metn key .
+If
+.meta key
+is found, then it return the hash table's cons cell which
+represents the association between
+.meta hash
+and
+.metn key .
+Otherwise, it returns
+.codn nil .
+
+If argument
+.meta init
+is specified, then the function will create
+an entry for
+.meta key
+in
+.meta hash
+whose value is that of
+.metn init .
The cons cell representing that association is returned.
-Note: for as long as the <key> continues to exist inside <hash>. modifying the
-car field of the returned cons has ramifications for the logical integrity of
-the hash. Modifying the cdr field has the effect of updating the association.
-
-.SS Function gethash
-
-.TP
-Syntax:
-
- (gethash <hash> <key> [<alt>])
-
-.TP
-Description:
-
-The gethash function searches hash table <hash> for key <key>. If the
+Note: for as long as the
+.meta key
+continues to exist inside
+.metn hash .
+modifying the
+.code car
+field of the returned cons has ramifications for the logical integrity of
+the hash. Modifying the
+.code cdr
+field has the effect of updating the association with a new value.
+
+.coNP Function @ gethash
+.synb
+.mets (gethash < hash < key <> [ alt ])
+.syne
+.desc
+The
+.code gethash
+function searches hash table
+.meta hash
+for key
+.metn key .
+If the
key is found then the associated value is returned. Otherwise, if
-the <alt> argument was specified, it is returned. If the <alt> argument
-was not specified, nil is returned.
-
-.SS Function sethash
-
-.TP
-Syntax:
-
- (sethash <hash> <key> <value>)
-
-.TP
-Description:
+the
+.meta alt
+argument was specified, it is returned. If the
+.meta alt
+argument
+was not specified,
+.code nil
+is returned.
-The sethash function places a value into <hash> table under the given <key>.
+.coNP Function @ sethash
+.synb
+.mets (sethash < hash < key << value )
+.syne
+.desc
+The
+.code sethash
+function places a value into
+.meta hash
+table under the given
+.metn key .
If a similar key already exists in the hash table, then that key's
-value is replaced by <value>. Otherwise, the <key> and <value> pair is
-newly inserted into <hash>.
-
-.SS Function pushhash
-
-.TP
-Syntax:
-
- (pushhash <hash> <key> <element>)
-
-.TP
-Description:
-
-The pushhash function is useful when the values stored in a hash table
-are lists. If the given <key> does not already exist in <hash>, then a list of
-length one is made which contains <element>, and stored in <hash> table under
-<key>. If the <key> already exists in the hash table, then the corresponding
-value must be a list. The <element> value is added to the front of that list,
-and the extended list then becomes the new value under <key>.
-
-.SS Function remhash
-
-.TP
-Syntax:
-
- (remhash <hash> <key>)
-
-.TP
-Description:
-
-The remhash function searches <hash> for a key similar to the
-<key>. If that key is found, then that key and its corresponding value are
+value is replaced by
+.metn value .
+Otherwise, the
+.meta key
+and
+.meta value
+pair is
+newly inserted into
+.metn hash .
+
+.coNP Function @ pushhash
+.synb
+.mets (pushhash < hash < key << element )
+.syne
+.desc
+The
+.code pushhash
+function is useful when the values stored in a hash table
+are lists. If the given
+.meta key
+does not already exist in
+.metn hash ,
+then a list of
+length one is made which contains
+.metn element ,
+and stored in
+.meta hash
+table under
+.metn key .
+If the
+.meta key
+already exists in the hash table, then the corresponding
+value must be a list. The
+.meta element
+value is added to the front of that list,
+and the extended list then becomes the new value under
+.metn key .
+
+.coNP Function @ remhash
+.synb
+.mets (remhash < hash << key )
+.syne
+.desc
+The
+.code remhash
+function searches
+.meta hash
+for a key similar to the
+.metn key .
+If that key is found, then that key and its corresponding value are
removed from the hash table.
-.SS Function hash-count
-
-.TP
-Syntax:
-
- (hash-count <hash>)
-
-.TP
-Description:
-
-The hash-count function returns an integer representing the number of
-key-value pairs stored in <hash>.
-
-.SS Function get-hash-userdata
-
-.TP
-Syntax:
-
- (get-hash-userdata <hash>)
-
-.TP
-Description:
-
-This function retrieves the user data object associated with <hash>.
-The user data object of a newly created hash table is initialized to nil.
-
-.SS Function set-hash-userdata
-
-.TP
-Syntax:
-
- (set-hash-userdata <hash> <object>)
-
-.TP
-Description:
-
-The set-hash-userdata replaces, with the <object>, the user data object
-associated with <hash>.
-
-.SS Function hashp
-
-.TP
-Syntax:
-
- (hashp <object>)
-
-.TP
-Description:
-
-The hashp function returns t if the <object> is a hash table,
-otherwise it returns nil.
-
-.SS Function maphash
-
-.TP
-Syntax:
-
- (maphash <hash> <binary-function>)
-
-.TP
-Description:
-
-The maphash function successively invokes binary-function for each key-value
-pair present in <hash>. The key and value are passed as arguments
-to <binary-function>.
-
-.SS Functions hash-eql and hash-equal
-
-.TP
-Syntax:
-
- (hash-eql <object>)
- (hash-equal <object>)
-
-.TP
-Description:
-
+.coNP Function @ hash-count
+.synb
+.mets (hash-count << hash )
+.syne
+.desc
+The
+.code hash-count
+function returns an integer representing the number of
+key-value pairs stored in
+.metn hash .
+
+.coNP Function @ get-hash-userdata
+.synb
+.mets (get-hash-userdata << hash )
+.syne
+.desc
+This function retrieves the user data object associated with
+.metn hash .
+The user data object of a newly-created hash table is initialized to
+.codn nil .
+
+.coNP Function @ set-hash-userdata
+.synb
+.mets (set-hash-userdata < hash << object )
+.syne
+.desc
+The
+.code set-hash-userdata
+replaces, with the
+.metn object ,
+the user data object
+associated with
+.metn hash .
+
+.coNP Function @ hashp
+.synb
+.mets (hashp << object )
+.syne
+.desc
+The
+.code hashp
+function returns
+.code t
+if the
+.meta object
+is a hash table,
+otherwise it returns
+.codn nil .
+
+.coNP Function @ maphash
+.synb
+.mets (maphash < hash << binary-function )
+.syne
+.desc
+The
+.code maphash
+function successively invokes
+.meta binary-function
+for each entry stored in
+.metn hash .
+Each entry's key and value are passed as arguments
+to
+.codn binary-function .
+
+The function returns
+.codn nil .
+
+.coNP Functions @ hash-eql and @ hash-equal
+.synb
+.mets (hash-eql << object )
+.mets (hash-equal << object )
+.syne
+.desc
These functions each compute an integer hash value from the internal
-representation of <object>, which satisfies the following properties.
-If two objects A and B are the same under the eql function, then
-(hash-eql A) and (hash-eql B) produce the same integer hash value. Similarly,
-if two objects A and B are the same under the equal function, then (hash-equal
-A) and (hash-equal B) each produce the same integer hash value. In all other
+representation of
+.metn object ,
+which satisfies the following properties.
+If two objects
+.code A
+and
+.code B
+are the same under the
+.code eql
+function, then
+.code (hash-eql A)
+and
+.code (hash-eql B)
+produce the same integer hash value. Similarly,
+if two objects
+.code A
+and
+.code B
+are the same under the
+.code equal
+function, then
+.code (hash-equal A)
+and
+.code (hash-equal B)
+each produce the same integer hash value. In all other
circumstances, the hash values of two distinct objects are unrelated, and
-may or may not be equal.
-
-.SS Functions hash_keys, hash_values, hash_pairs, and hash_alist
-
-.TP
-Syntax:
- (hash-keys <hash>)
- (hash-values <hash>)
- (hash-pairs <hash>)
- (hash-alist <hash>)
-
-.TP
-Description:
-
-These functions retrieve the bulk key-value data of hash table <hash>
-in various ways. hash-keys retrieves a list of the keys. hash-values
-retrieves a list of the values. hash-pairs retrieves a list of pairs,
+may or may not be the same.
+
+.coNP Functions @, hash_keys @, hash_values @ hash_pairs and @ hash_alist
+.synb
+.mets (hash-keys << hash )
+.mets (hash-values << hash )
+.mets (hash-pairs << hash )
+.mets (hash-alist << hash )
+.syne
+.desc
+These functions retrieve the bulk key-value data of hash table
+.meta hash
+in various ways.
+.code hash-keys
+retrieves a list of the keys.
+.code hash-values
+retrieves a list of the values.
+.code hash-pairs
+retrieves a list of pairs,
which are two-element lists consisting of the key, followed by the value.
-Finally, hash-pairs retrieves the key-value pairs as a Lisp association list:
-a list of cons cells whose car fields are keys, and whose cdr fields
-are the values.
+Finally,
+.code hash-pairs
+retrieves the key-value pairs as a Lisp association list:
+a list of cons cells whose
+.code car
+fields are keys, and whose
+.code cdr
+fields are the values.
These functions all retrieve the keys and values in the
-same order. For example, if the keys are retrieved with hash-keys,
-and the values with hash-values, then the corresponding entries from
-each list correspond to the pairs in the hash table.
-
-.SS Operator dohash
-
-.TP
-Syntax:
-
- (dohash (<key-var> <value-var> <hash-form> [<result-form>])
- <body-form>*)
-
-.TP
-Description:
-
-The dohash operator iterates over a hash table. The <hash-form> expression must
-evaluate to an object of hash table type. The <key-var> and <value-var>
+same order. For example, if the keys are retrieved with
+.codn hash-keys ,
+and the values with
+.codn hash-values ,
+then the corresponding entries from
+each list pairwise correspond to the pairs in
+.metn hash .
+
+.coNP Operator @ dohash
+.synb
+.mets (dohash ( < key-var < value-var < hash-form <> [ result-form ])
+.mets \ \ << body-form *)
+.syne
+.desc
+The
+.code dohash
+operator iterates over a hash table. The
+.meta hash-form
+expression must
+evaluate to an object of hash table type. The
+.meta key-var
+and
+.meta value-var
arguments must be symbols suitable for use as variable names.
Bindings are established for these variables over the scope of the
-<body-form>-s and the optional result form.
-
-For each element in the hash table, the <key-var> and <value-var>
+.metn body-form s
+and the optional
+.metn result-form .
+
+For each element in the hash table, the
+.meta key-var
+and
+.meta value-var
variables are set to the key and value of that entry, respectively,
-and each <body-form>, if there are any, is evaluated.
-
-When all of the entries of the table are thus processed, the <result-form> is
-evaluated, and its return value becomes the return value of the dohash form. If
-there is no <result-form>, the return value is nil.
-
-The <result-form> and <body-form>-s are in the scope of an implicit anonymous
+and each
+.metn body-form ,
+if there are any, is evaluated.
+
+When all of the entries of the table are thus processed, the
+.meta result-form
+is evaluated, and its return value becomes the return value of the dohash form.
+If there is no
+.metn result-form ,
+the return value is
+.codn nil .
+
+The
+.meta result-form
+and
+.metn body-form s
+are in the scope of an implicit anonymous
block, which means that it is possible to terminate the execution of
-dohash early using (return) or (return <value>).
-
-.SS Functions hash-uni, hash-diff, hash-isec
-
-.TP
-Syntax:
-
- (hash-uni <hash1> <hash2> [<join-func>])
- (hash-diff <hash1> <hash2>)
- (hash-isec <hash1> <hash2> [<join-func>])
-
-.TP
-Description:
-
+dohash early using
+.cblk
+.meti (return << value )
+.cble
+or
+.codn (return) .
+
+.coNP Functions @, hash-uni @ hash-diff and @ hash-isec
+.synb
+.mets (hash-uni < hash1 < hash2 <> [ join-func ])
+.mets (hash-diff < hash1 << hash2 )
+.mets (hash-isec < hash1 < hash2 <> [ join-func ])
+.syne
+.desc
These functions perform basic set operations on hash tables in a nondestructive
way, returning a new hash table without altering the inputs. The arguments
-<hash1> and <hash2> must be compatible hash tables. This means that their keys
+.meta hash1
+and
+.meta hash2
+must be compatible hash tables. This means that their keys
must use the same kind of equality.
-The resulting hash table inherits attributes from <hash1>, as if by the
-make-similar-hash operation. If <hash1> has userdata, the resulting hash table
-has the same userdata. If <hash1> has weak keys, the resulting table has weak
+The resulting hash table inherits attributes from
+.metn hash1 ,
+as if created by the
+.code make-similar-hash
+function. If
+.meta hash1
+has userdata, the resulting hash table
+has the same userdata. If
+.meta hash1
+has weak keys, the resulting table has weak
keys, and so forth.
-The hash-uni function performs a set union. The resulting hash contains all of
-the keys from <hash1> and all of the keys from <hash2>, and their corresponding
-values. If a key occurs both in <hash1> and <hash2>, then it occurs only once
-in the resulting hash. In this case, if the <join-func> argument is not given
-specified, value associated with this key is the one from <hash1>. If
-<join-func> is specified then it is called with two arguments: the respective
-data items from <hash1> and <hash2>. The return value of this function is used
+The
+.code hash-uni
+function performs a set union. The resulting hash contains all of
+the keys from
+.meta hash1
+and all of the keys from
+.metn hash2 ,
+and their corresponding
+values. If a key occurs both in
+.meta hash1
+and
+.metn hash2 ,
+then it occurs only once
+in the resulting hash. In this case, if the
+.meta join-func
+argument is not given,
+the value associated with this key is the one from
+.metn hash1 .
+If
+.meta join-func
+is specified then it is called with two arguments: the respective
+data items from
+.meta hash1
+and
+.metn hash2 .
+The return value of this function is used
as the value in the union hash.
-The hash-diff function performs a set difference. First, a copy of <hash1> is
-made as if by the copy-has function. Then from this copy, all keys which occur
-in <hash2> are deleted.
-
-The hash-isec function performs a set intersection. The resulting hash contains
-only those keys which occur both in <hash1> and <hash2>. If <join-func> is not
-specified, the values selected for these common keys are those from <hash1>.
-If <join-func> is specified, then for each key which occurs in both <hash1> and
-<hash2>, it is called with two arguments: the respective data items. The return
+The
+.code hash-diff
+function performs a set difference. First, a copy of
+.meta hash1
+is made as if by the
+.code copy-hash
+function. Then from this copy, all keys which occur
+in
+.code hash2
+are deleted.
+
+The
+.code hash-isec
+function performs a set intersection. The resulting hash contains
+only those keys which occur both in
+.meta hash1
+and
+.metn hash2 .
+If
+.meta join-func
+is not
+specified, the values selected for these common keys are those from
+.metn hash1 .
+If
+.meta join-func
+is specified, then for each key which occurs in both
+.meta hash1
+and
+.metn hash2 ,
+it is called with two arguments: the respective data items. The return
value is then used as the data item in the intersection hash.
-.SH PARTIAL EVALUATION AND COMBINATORS
-
-.SS Macros op and do
-
-.TP
-Syntax:
-
- (op <form>+)
- (do <form>+)
-
-.TP
-Description:
-
-The op and do macro operators are similar.
-
-Like the lambda operator, the op operator creates an anonymous function.
+.SS* Partial Evaluation and Combinators
+.coNP Macros @ op and @ do
+.synb
+.mets (op << form +)
+.mets (do << form +)
+.syne
+.desc
+The
+.code op
+and
+.code do
+macro operators are similar.
+
+Like the lambda operator, the
+.code op
+operator creates an anonymous function based on its syntax.
The difference is that the arguments of the function are implicit, or
-optionally specified within the function body.
-
-Also, the <form> arguments of op are implicitly turned into a DWIM expression,
-which means that argument evaluation follows Lisp-1 rules. (See the dwim
-operator below).
-
-The do operator is like the op operator with the following difference:
-the <form> arguments of op are not implicitly treated as a DWIM expression,
+optionally specified within the function body, rather than as a formal
+parameter list before the body.
+
+Also, the
+.meta form
+arguments of
+.code op
+are implicitly turned into a DWIM expression,
+which means that argument evaluation follows Lisp-1 rules. (See the
+.code dwim
+operator).
+
+The.
+.code do
+operator is like the
+.code op
+operator with the following difference:
+the
+.meta form
+arguments of
+.code op
+are not implicitly treated as a DWIM expression,
but as an ordinary expression. In particular, this means that operator
-syntax is permitted. Note that the syntax (op @1) makes sense, since
-the argument can be a function, which will be invoked, but (do @1) doesn't
-make sense because it will produce a Lisp-2 form like (#:arg1 ...) referring
-to nonexistent function #:arg1. This is why the operator is called "do": it
-requires some operation. Moreover, it can be used with imperative constructs
-which are not functions, like set: like set: for instance (do set x) produces
+syntax is permitted. Note that the syntax
+.code (op @1)
+makes sense, since
+the argument can be a function, which will be invoked, but
+.code (do @1)
+doesn't
+make sense because it will produce a Lisp-2 form like
+.code (#:arg1 ...)
+referring
+to nonexistent function
+.codn #:arg1 .
+Because it accepts operators,
+.code do
+can be used with imperative constructs
+which are not functions, like set: like set: for instance
+.code (do set x)
+produces
an anonymous function which, if called with one argument, stores that argument
-into x.
+into
+.codn x .
The argument forms are arbitrary expressions, within which a special
convention is permitted:
-
-.IP @<num>
-
-A number preceded by a @ is a metanumber. This is a special syntax
-which denotes an argument. For instance @2 means that the second argument of
-the anonymous function is to be substituted in place of the @2. If @2 is used
-it means that @1 also has to appear somewhere, otherwise the op
-construct is erroneous.
-
-.IP @rest
-
-The meta-symbol @rest indicates that any trailing arguments to the
-function are to be inserted there. If the form does not contain
-any @<num> syntax or @rest syntax, then @rest is implicitly
-inserted. What this means is that, for example, since the form (op foo) does
-not contain any numeric positional arguments like @1, and does not contain
-@rest, it is actually a shorthand for (op foo . @rest).
-
-The actions of form may be understood by these examples, which show
-how op is rewritten to lambda. However, note that the real translator
+.RS
+.meIP >> @ num
+A number preceded by a
+.code @
+is a metanumber. This is a special syntax
+which denotes an argument. For instance
+.code @2
+means that the second argument of
+the anonymous function is to be substituted in place of the
+.codn @2 .
+.code op
+generates a function which has a number of required arguments equal to the
+highest value of
+.meta num
+apearing in a
+.cblk
+.mati >> @ num
+.cble
+construct in the body. For instance
+.code (op car @3)
+generates a three-argument function (which passes its third
+argument to
+.codn car ,
+returning the result, and ignores its first two arguments).
+There is no way to use
+.code op
+to generate functions which have optional arguments.
+.meIP < @rest
+If the meta-symbol
+.meta @rest
+appears in the
+.code op
+syntax, it explicitly denotes the list of trailing arguments,
+allowing them to be placed anywhere in the expression.
+.RE
+
+Functions generated by
+.code op
+are always variadic; they always take additional arguments after
+any required ones, whether or not the
+.meta @rest
+syntax is used.
+
+If the body does not contain
+any
+.meta @num
+or
+.meta @rest
+syntax, then
+.code @rest
+is implicitly inserted. What this means is that, for example, since
+the form
+.code (op foo)
+does not contain any numeric positional arguments like
+.codn @1 ,
+and does not contain
+.codn @rest ,
+it is actually a shorthand for
+.codn (op foo . @rest) :
+a function which applies all of its arguments to
+.codn foo .
+
+The actions of
+.code op
+be understood by these examples, which show
+how
+.code op
+is rewritten to lambda. However, note that the real translator
uses generated symbols for the arguments, which are not equal to any
symbols in the program.
+.cblk
(op) -> invalid
(op +) -> (lambda rest [+ . rest])
@@ -12528,7 +19633,7 @@ symbols in the program.
(op @1 @2) -> (lambda (arg1 arg2 . rest) [arg1 arg2])
- (op foo @1 (@2) (bar @3)) -> (lambda (arg1 arg2 arg3 . rest)
+ (op foo @1 (@2) (bar @3)) -> (lambda (arg1 arg2 arg3 . rest)
[foo arg1 (arg2) (bar arg3)])
(op foo @rest @1) -> (lambda (arg1 . rest) [foo rest arg1])
@@ -12538,138 +19643,246 @@ symbols in the program.
(do @1 @2) -> (lambda (arg1 arg2 . rest) (arg1 arg2))
(do foo @rest @1) -> (lambda (arg1 . rest) (foo rest arg1))
-
-Note that if argument @<n> appears, it is not necessary
-for arguments @1 through @<n-1> to appear. The function
-will have n arguments:
-
+.cble
+
+Note that if argument
+.meta @n
+appears, it is not necessary
+for arguments
+.meta @1
+through
+.meta @n-1
+to appear. The function will have
+.code n
+arguments:
+
+.cblk
(op @3) -> (lambda (arg1 arg2 arg3 . rest) [arg3])
+.cble
+
+The
+.code op
+and
+.code do
+operators can be nested, in any combination. This raises the
+question: if a metanumber like
+.code @1
+or
+.code @rest
+occurs in an
+.code op
+that is nested
+within an
+.codn op , what is the meaning?
+A metanumber always belongs with the inner-most op or do operator. So for
+instance
+.code (op (op @1))
+means that an
+.code (op @1)
+expression is nested
+within an
+.code op
+expression which itself contains no meta-syntax.
+The
+.code @1
+belongs with the inner op.
+
+There is a way for an inner
+.code op
+to refer to an outer op metanumber argument. This is
+expresed by adding an extra
+.code @
+prefix for every level of escape. For example in
+.code (op (op @@1))
+the
+.code @@1
+belongs to the outer
+.codn op :
+it is the same as
+.code @1
+appearing in the outer
+.codn op .
+That is to say,
+in the expression
+.codn (op @1 (op @@1)) ,
+the
+.code @1
+and
+.code @@1
+are the same thing:
+both are parameter 1 of the lambda function generated by the outer
+.codn op .
+By contrast, in the expression
+.code (op @1 (op @1))
+there are two different parameters:
+the first
+.code @1
+is argument of the outer function, and the second
+.code @1
+is the first argument of the inner function. Of course, if there
+are three levels of nesting, then three
+.code @
+meta-prefixes are needed to insert
+a parameter from the outermost
+.code op
+into the innermost
+.codn op .
-.PP
-
-.TP
-Examples:
+.TP* Examples:
+.cblk
;; Take a list of pairs and produce a list in which those pairs
;; are reversed.
(mapcar (op list @2 @1) '((1 2) (a b))) -> ((2 1) (b a))
-
-.TP
-Nested op:
-
-The op and do operators can be nested, in any combination. This raises the
-question: if a metanumber like @1 or @rest occurs in an op that is nested
-within an op, what is the meaning?
-
-A metanumber always belongs with the inner-most op or do operator. So for
-instance (op (op @1)) means that an (op @1) expression is nested
-within an op expression. The @1 belongs with the inner op.
-
-There is a way to refer to an outer op metanumber argument, we need to
-add a meta for every level of escape. For example in (op (op @@1))
-the @@1 belongs to the outer op: it is the same as @1. That is to say,
-in the expression (op @1 (op @@1)), the @1 and @@1 are the same thing:
-parameter 1 of the lambda function generated by the outer op.
-In the expression (op @1 (op @1)) there are two different parameters:
-the first @1 is argument of the outer function, and the second @1
-is the first argument of the inner function. Of course, if there
-are three levels of nesting, then three metas are needed to insert
-a parameter from the outermost op, into the innermost op.
-
-.SS Macros ap, ip, ado and ido.
-
-.TP
-Syntax:
-
- (ap <form>+)
- (ip <form>+)
- (ado <form>+)
- (ido <form>+)
-
-.TP
-Description:
-
-The ap macro is based on the op macro and has identical argument
+.cble
+
+.coNP Macros @, ap @, ip @ ado and @ ido.
+.synb
+.mets (ap << form +)
+.mets (ip << form +)
+.mets (ado << form +)
+.mets (ido << form +)
+.syne
+.desc
+The
+.code ap
+macro is based on the
+.code op
+macro and has identical argument
conventions.
-The ap macro analyzes its arguments and produces a function, in exactly the
-same same way as the op macro. It then returns a different one-argument
-function which accepts a list, and calls that function, applying the
-list as arguments.
+The
+.code ap
+macro analyzes its arguments and produces a function
+.metn f ,
+in exactly the same same way as the
+.code op
+macro. However, instead of returning
+.metn f ,
+directly, it returns a different function
+.metn g ,
+which is a one-argument function which accepts a list,
+and then applies the list as arguments to
+.metn f .
In other words, the following equivalence holds:
+.cblk
(ap form ...) <--> (apf (op form ...))
+.cble
+
+The
+.code ap
+macro nests properly with
+.code op
+and
+.codn do ,
+in any combination, in regard to the
+.meta ...@@n
+notation.
-The ap macro nests properly with op and do, in any combination, in regard
-to the @@n notation.
-
-The ip macro is very similar to the ap macro, except that it is based
-on the semantics of the function iapply rather than apply, according
+The
+.ode ip
+macro is very similar to the
+.code ap
+macro, except that it is based
+on the semantics of the function
+.code iapply
+rather than
+.codn apply ,
+according
to the following equivalence:
+.cblk
(ip form ...) <--> (ipf (op form ...))
-
-The ado and ido macros is related to do macro in the same way that ap and ip
-are related to op. They produce a one-argument function is produced which works
+.cble
+
+The
+.code ado
+and
+.code ido
+macros are related to do macro in the same way that
+.code ap
+and
+.code ip
+are related to
+.codn op .
+They produce a one-argument function which works
as if by applying its arguments to the function generated by do,
according to the following equivalence:
+.cblk
(ado form ...) <--> (apf (do form ...))
(ido form ...) <--> (ipf (do form ...))
+.cblk
+
+See also: the
+.code apf
+and
+.code ipf
+functions.
+
+.coNP Macro @ ret
+.synb
+.mets (ret << form )
+.syne
+.desc
+The
+.code ret
+macro's
+.meta form
+argument is treated similarly to the second and subsequent arguments of the
+.code op
+operator.
-See also: the apf and ipf functions.
-
-.SS Macro ret
-
-.TP
-Syntax:
-
- (ret <form>)
-
-.TP
-Description:
-
-The ret macro's argument is treated similarly to the arguments of the op
-operator, except that the first form of the op operator denotes
-a function to be called where as the one and only argument form of the
-ret operator denotes a value.
+The
+.code ret
+macro produces a function which takes any number of arguments,
+and returns the value specified by
+.metn form .
-The ret macro produces a function which takes any number of arguments,
-and returns the value specified by <form>.
+.meta form
+can contain
+.code op
+meta syntax like
+.meta @n
+and
+.codn @rest .
The following equivalence holds:
- (ret x) <--> (op identity (progn @rest x))
-
-where the @rest parameter is mentioned for its side effect of making
-op generate a function which accepts any number of arguments.
-
-The expression (ret @2) returns a function similar to
-(lambda (x y . z) y).
-
-The expression (ret 42) returns a function similar to
-(lambda (. rest) 42).
-
-.SS Function chain
-
-.TP
-Syntax:
-
- (chain <func>*)
-
-.TP
-Description:
-
-The chain function accepts zero or more functions as arguments, and returns
+.cblk
+ (ret x) <--> (op identity x))
+.cble
+
+Thus the expression
+.code (ret @2)
+returns a function similar to
+.codn (lambda (x y . z) y) ,
+and the expression
+.code (ret 42)
+returns a function similar to
+.codn (lambda (. rest) 42) .
+
+.coNP Function @ chain
+.synb
+.mets (chain << func *)
+.syne
+.desc
+The
+.code chain
+function accepts zero or more functions as arguments, and returns
a single function, called the chained function, which represents the chained
application of those functions, in left to right order.
-If chain is given no arguments, then it returns a variadic function which
-ignores all of its arguments and returns nil.
+If
+.code chain
+is given no arguments, then it returns a variadic function which
+ignores all of its arguments and returns
+.codn nil .
Otherwise, the first function may accept any number of arguments. The second
and subsequent functions, if any, must accept one argument.
@@ -12680,218 +19893,358 @@ function. The return value of that call is then passed to the second
function, and the return value of that call is passed to the third function
and so on. The final return value is returned to the caller.
-.TP
-Example:
+.TP* Example:
+.cblk
(call [chain + (op * 2)] 3 4) -> 14
-
-In this example, a two-element chain is formed from the + function
-and the function produced by (op * 2) which is a one-argument
+.cble
+
+In this example, a two-element chain is formed from the
+.code +
+function
+and the function produced by
+.code (op * 2)
+which is a one-argument
function that returns the value of its argument multiplied by two.
-(See the definition of the op operator).
-
-The chained function is invoked using the call function, with the arguments 3
-and 4. The chained evaluation begins by passing 3 and 4 to the + function,
-which yields 7. This 7 is then passed to the (op * 2) doubling function,
-resulting in 14.
+(See the definition of the
+.code op
+operator).
+
+The chained function is invoked using the
+.code call
+function, with the arguments
+.code 3
+and
+.codn 4 .
+The chained evaluation begins by passing
+.code 3
+and
+.code 4
+to
+.codn + ,
+which yields
+.codn 7 .
+This
+.code 7
+is then passed to the
+.code (op * 2)
+doubling function, resulting in
+.codn 14 .
A way to write the above example without the use of the DWIM brackets and the
op operator is this:
+.cblk
(call (chain (fun +) (lambda (x) (* 2 x))) 3 4)
-
-.SS Function juxt
-
-.TP
-Syntax:
-
- (juxt <func>*)
-
-.TP
-Description:
-
-The juxt function accepts a variable number of arguments which are functions.
-It combines these into a single function which, when invoked, passes its arguments
-to each of the functions, and collects the results into a list. The results
+.cble
+
+.coNP Function @ juxt
+.synb
+.mets (juxt << func *)
+.syne
+.desc
+The
+.code juxt
+function accepts a variable number of arguments which are functions. It
+combines these into a single function which, when invoked, passes its arguments
+to each of these functions, and collects the results into a list.
Note: the juxt function can be understood in terms of the following reference
implementation:
+.cblk
(defun juxt (funcs)
(lambda (. args)
(mapcar (lambda (fun)
(apply fun args))
funcs)))
+.cble
-.TP
-Example:
+.TP* Example:
- ;; separate list (1 2 3 4 5 6) into lists of evens and odds, which end up
- ;; juxtaposed in the output list:
+.cblk
+ ;; separate list (1 2 3 4 5 6) into lists of evens and odds,
+ ;; which end up juxtaposed in the output list:
- [(op [juxt keep-if remove-if] evenp) '(1 2 3 4 5 6)] -> ((2 4 6) (1 3 5))
+ [(op [juxt keep-if remove-if] evenp)
+ '(1 2 3 4 5 6)] -> ((2 4 6) (1 3 5))
;; call several functions on 1, collecting their results:
[[juxt (op + 1) (op - 1) evenp sin cos] 1]'
-> (2 0 nil 0.841470984807897 0.54030230586814)
-
-.SS Functions andf and orf
-
-.TP
-Syntax:
-
- (andf <func>*)
- (orf <func>*)
-
-.TP
-Description:
-
-The andf and orf functions are the functional equivalent of the and and or
+.cble
+
+.coNP Functions @ andf and @ orf
+.synb
+.mets (andf << func *)
+.mets (orf << func *)
+.syne
+.desc
+The
+.code andf
+and
+.code orf
+functions are the functional equivalent of the
+.code and
+and
+.code or
operators. These functions accept multiple functions and return a new function
which represents the logical combination of those functions.
-The input functions should have the same arity. Or, rather, there should exist
-some common argument arity with which they can all be invoked. The resulting
-combined function is then callable with that many arguments.
+The input functions should have the same arity. Failing that, there should
+exist some common argument arity with which each of these can be invoked. The
+resulting combined function is then callable with that many arguments.
-The andf operator returns a function which combines the input functions with
-short-circuiting logical conjunction. The resulting function passes its
+The
+.code andf
+function returns a function which combines the input functions with
+a short-circuiting logical conjunction. The resulting function passes its
arguments to the functions successively, in left to right order. As soon as any
-of the functions returns nil, then nil is returned immediately, and the
+of the functions returns
+.codn nil ,
+then nil is returned immediately, and the
remaining functions are not called. Otherwise, if none of the functions return
-nil, then the value returned by the last function is returned. If the list of
-functions is empty, then t is returned. That is, (andf) returns a function
-which accepts any arguments, and returns t.
-
-The orf operator combines the input functions with a short-circuiting logical
-disjunction. The function produced by orf passes its arguments down to the
+.codn nil ,
+then the value returned by the last function is returned. If the list of
+functions is empty, then
+.code t
+is returned. That is,
+.code (andf)
+returns a function
+which accepts any arguments, and returns
+.codn t .
+
+The
+.code orf
+function combines the input functions with a short-circuiting logical
+disjunction. The function produced by
+.code orf
+passes its arguments down to the
functions successively, in left to right order. As soon as any function
-returns a non-nil value, that value is returned and the remaining functions are
-not called. If all functions return nil, then nil is returned. The expression
-(orf) returns a function which accepts any arguments and returns nil.
-
-
-.SS Functions iff and iffi
-
-.TP
-Syntax:
-
- (iff <cond-func> <then-func> [<else-func>])
- (iffi <cond-func> <then-func> [<else-func>])
-
-.TP
-Description:
-
-The iff function is the functional equivalent of the if operator. It accepts
+returns a
+.cod2 non- nil
+value, that value is returned and the remaining functions are
+not called. If all functions return
+.codn nil ,
+then
+.code nil
+is returned. The expression
+.code (orf)
+returns a function which accepts any arguments and returns
+.codn nil .
+
+.coNP Functions @ iff and @ iffi
+.synb
+.mets (iff < cond-func < then-func <> [ else-func ])
+.mets (iffi < cond-func < then-func <> [ else-func ])
+.syne
+.desc
+The
+.code iff
+function is the functional equivalent of the
+.code if
+operator. It accepts
functional arguments and returns a function.
-The resulting function takes its arguments and applies them to <cond-func>. If
-<cond-func> yields true, then the arguments are passed to <then-func> and the
-resulting value is returned. Otherwise the arguments are passed to <else-func>
+The resulting function takes its arguments and applies them to
+.metn cond-func .
+If
+.meta cond-func
+yields true, then the arguments are passed to
+.meta then-func
+and the
+resulting value is returned. Otherwise the arguments are passed to
+.meta else-func
and the resulting value is returned.
-If <then-func> needs to be called, but is nil, then nil is returned
-immediately. Likewise, if <else-func> needs to be called, but is omitted or
-nil, then nil is returned.
+If
+.meta then-func
+needs to be called, but is
+.codn nil ,
+then
+.code nil
+is returned immediately. Likewise, if
+.meta else-func
+needs to be called, but is omitted or
+.codn nil ,
+then
+.code nil
+is returned.
-The iffi function differs from iff only in the defaulting behavior with respect
-to the <else-func> argument. The following equivalences hold:
+The
+.code iffi
+function differs from
+.code iff
+only in the defaulting behavior with respect
+to the
+.meta else-func
+argument. The following equivalences hold:
+.cblk
(iffi a b c) <--> (iff a b c)
(iffi a b) <--> (iff a b identity)
(iffi a b nil) <--> (iff a b identity)
+.cble
+
+The
+.code iffi
+function defaults to the identity function when
+.meta else-func
+is
+omitted or
+.codn nil ,
+and therefore is useful in situations when one value is to be
+replaced with another one when the condition is true, otherwise
+preserved.
-The iffi function defaults to the identity function when <else-func> is
-omitted or nil, and therefore is useful in situations when one value is to be
-replaced with another one when the condition is true, otherwise left alone.
-
-.SS Functions tf and nilf
-
-.TP
-Syntax:
+.coNP Functions @ tf and @ nilf
+.synb
+.mets (tf << arg *)
+.mets (nilf << arg *)
+.syne
+.desc
+The
+.code tf
+and
+.code nilf
+functions take zero or more arguments, and ignore them.
+The
+.code tf
+function returns
+.codn t ,
+and the
+.code nilf
+function returns
+.codn nil .
+
+Note: the following equivalences hold between these functions and the
+.code ret
+operator, and
+.code retf
+function.
- (tf <arg>*)
- (nilf <arg>*)
+.cblk
+ (fun tf) <--> (ret t) <--> (retf t)
+ (fun nilf) <--> (ret nil) <--> (ret) <--> (retf nil)
+.cble
-.TP
-Description:
+In Lisp-1-style code,
+.code tf
+and
+.code nilf
+behave like constants which can replace uses of
+.code (ret t)
+and
+.codn (ret nil) :
-The tf and nilf functions take zero or more arguments, and ignore them.
-The tf function returns t, and the nilf function returns nil.
+.cblk
+ [mapcar (ret nil) list] <--> [mapcar nilf list]
+.cble
-.TP
-Example:
+.TP* Example:
+.cblk
;; tf and nilf are useful when functions are chained together.
;; test whether (trunc n 2) is odd.
(defun trunc-n-2-odd (n)
[[chain (op trunc @1 2) [iff oddp tf nilf]] n)
+.cble
-In this example, two functions are chained together, and n is passed
+In this example, two functions are chained together, and
+.code n
+is passed
through the chain such that it is first divided by two via the
-function denoted by (op trunc @1 2) and then the result is passed into the
-function denoted by [iff oddp tf nilf]. The iff function passes its
-argument into oddp, and if oddp yields true, it passes the same argument to tf.
-Here tf proves its utility by ignoring that value and returning t.
-If the argument (the divided value) passed into iff is even, then
-iff passes it into the nilf function, which ignores the value and
-returns nil.
-
-.SS Function retf
-
-.TP
-Syntax:
-
- (retf <value>)
-
-.TP
-Description:
-
-The retf function returns a function. That function can take zero or
-more arguments. When called, it ignores its arguments and returns <value>.
-
-See also: the ret macro.
-
-.TP
-Example:
-
- ;; the function returned by (retf 42) ignores 1 2 3 and returns 42.
+function denoted by
+.code (op trunc @1 2)
+and then the result is passed into the
+function denoted by
+.codn [iff oddp tf nilf] .
+The
+.code iff
+function passes its argument into
+.codn oddp ,
+and if
+.code oddp
+yields true, it passes the same argument to
+.codn tf .
+Here
+.code tf
+proves its utility by ignoring that value and returning
+.codn t .
+If the argument (the divided value) passed into
+.code iff
+is even, then iff passes it into the
+.code nilf
+function, which ignores the value and returns
+.codn nil .
+
+.coNP Function retf
+.synb
+.mets (retf << value )
+.syne
+.desc
+The
+.code retf
+function returns a function. That function can take zero or
+more arguments. When called, it ignores its arguments and returns
+.metn value .
+
+See also: the
+.code ret
+macro.
+
+.TP* Example:
+
+.cblk
+ ;; the function returned by (retf 42)
+ ;; ignores 1 2 3 and returns 42.
(call (retf 42) 1 2 3) -> 42
-
-.SS Functions apf and ipf
-
-.TP
-Syntax:
-
- (apf <function>)
- (ipf <function>)
-
-.TP
-Description:
-
-The apf function returns a one-argument function which accepts
+.cble
+
+.coNP Functions @ apf and @ ipf
+.synb
+.mets (apf << function )
+.mets (ipf << function )
+.syne
+.desc
+The
+.code apf
+function returns a one-argument function which accepts
a list. When the function is called, it treats the list as
-argument which are applied to <function> as if by apply. It returns whatever
-<function> returns.
-
-The ipf function is similar to apf, except that the returned
-function applies arguments as if by iapply rather than apply.
-
-See also: the ap macro.
-
-.TP
-Example:
-
- ;; Function returned by [apf +] accepts (1 2 3) list and
- ;; applies it to +, as if (+ 1 2 3) were called.
+argument which are applied to
+.meta function
+as if by apply. It returns whatever
+.meta function
+returns.
+
+The
+.code ipf
+function is similar to
+.codn apf ,
+except that the returned
+function applies arguments as if by
+.code iapply
+rather than
+.codn apply .
+
+See also: the
+.code ap
+macro.
+
+.TP* Example:
+
+.cblk
+ ;; Function returned by [apf +] accepts the
+ ;; (1 2 3) list and applies it to +, as
+ ;; if (+ 1 2 3) were called.
(call [apf +] '(1 2 3)) -> 6
+.cble
-.SH INPUT AND OUTPUT (STREAMS)
-
+.SS* Input and Output (Streams)
TXR Lisp supports input and output streams of various kinds, with
generic operations that work across the stream types.
@@ -12899,83 +20252,135 @@ In general, I/O errors are usually turned into exceptions. When the description
of error reporting is omitted from the description of a function, it can be
assumed that it throws an error.
-.SS Special variables *stdout*, *stddebug*, *stdin*, *stderr* and *stdnull*
-
-These variables hold predefined stream objects. The *stdin*, *stdout* and
-*stderr* streams closely correspond to the underlying operating system streams.
+.coNP Special variables @, *stdout* @, *stddebug* @, *stdin* @ *stderr* and @ *stdnull*
+.desc
+These variables hold predefined stream objects. The
+.codn *stdin* ,
+.code *stdout*
+and
+.code *stderr*
+streams closely correspond to the underlying operating system streams.
Various I/O functions require stream objects as arguments.
-The *stddebug* stream goes to the same destination as *stdout*, but is
-a separate object which can be redirected independently, allowing debugging
-output to be separated from normal output.
+The
+.code *stddebug*
+stream goes to the same destination as
+.codn *stdout* ,
+but is a separate object which can be redirected independently, allowing
+debugging output to be separated from normal output.
-The *stdnull* stream is a special kind of stream called a null stream.
+The
+.code *stdnull*
+stream is a special kind of stream called a null stream.
This stream is not connected to any device or file. It is similar to
-the /dev/null device on Unix, but does not involve the operating system.
-
-.SS Function format
-
-.TP
-Syntax:
-
- (format <stream-designator> <format-string> <format-arg>*)
-
-.TP
-Description:
-
-The format function performs output to a stream given by <stream-designator>,
-by interpreting the actions implicit in a <format-string>, incorporating
-material pulled from additional arguments given by <format-arg>*. Though the
-function is simple to invoke, there is complexity in format string language,
-which is documented below.
-
-The <stream-designator> argument can be a stream object, or one of the values t
-and nil. The value t serves as a shorthand for *stdout*. The value nil
+the
+.code /dev/null
+device on Unix, but does not involve the operating system.
+
+.coNP Function @ format
+.synb
+.mets (format < stream-designator < format-string << format-arg *)
+.syne
+.desc
+The
+.code format
+function performs output to a stream given by
+.metn stream-designator ,
+by interpreting the actions implicit in a
+.metn format-string ,
+incorporating material pulled from additional arguments given by
+.cblk
+.meti << format-arg *.
+.cble
+Though the function is simple to invoke, there is complexity in format string
+language, which is documented below.
+
+The
+.meta stream-designator
+argument can be a stream object, or one of the values
+.code t
+or
+.codn nil .
+The value
+.code t
+serves as a shorthand for
+.codn *stdout* .
+The value
+.code nil
means that the function will send output into a newly instantiated string
output stream, and then return the resulting string.
-.TP
-Format string syntax:
+.TP* "Format string syntax:"
-Within <format-string>, most characters represent themselves. Those
-characters are simply output. The character ~ (tilde) introduces formatting
-directives, which are denoted by a letter.
+Within
+.metn format-string ,
+most characters represent themselves. Those
+characters are simply output. The character
+.code ~
+(tilde) introduces formatting
+directives, which are denoted by a single character, usually a letter.
-The special sequence ~~ (tilde-tilde) codes a single tilde. Nothing is
+The special sequence
+.code ~~
+(tilde-tilde) encodes a single tilde. Nothing is
permitted between the two tildes.
The syntax of a directive is generally as follows:
- ~[<width>[,<precision>]]<letter>
+.cblk
+.mets ~[ [ < width ] [ >> , precision ] ] < letter
+.cble
-The <letter> is a single alphabetic character which determines the
+The
+.meta letter
+is a single alphabetic character which determines the
general action of the directive. The optional width and precision
-can be numeric digits, or special codes documented below.
-
-.TP
-width
+can be numeric digits, or special codes documented below.
-The width specifier consists of an optional < (left angle bracket) character,
+.RS
+.meIP < width
+The width specifier consists of an optional
+.code <
+(left angle bracket) character,
followed by an optional width specification.
-If the < character is present, then the printing will be left-adjusted within
-this field. Otherwise it will be right-adjusted by default.
+If the leading
+.code <
+character is present, then the printing will be left-adjusted within
+this field. Otherwise it will be right-adjusted by default.
-The width can be specified as a decimal integer, or as the character *. The *
+The width can be specified as a decimal integer, or as the character
+.codn * .
+The
+.code *
notation means that instead of digits, the value of the next argument is
consumed, and expected to be an integer which specifies the width. If that
-integer value is negative, then the field will be left-adjusted.
-If the value is positive, but the < character is present in the width
-specifier, then the field is left adjusted also.
-
-.TP
-precision
-
-The precision specifier consists of an optional combination of the
-special leading characters 0 (the "leading zero flag"), + (print a sign for
-positive values") or space (print a space in place of a positive sign),
-followed by a specification of the precision value, which is either a decimal
-integer that does not begin with a zero digit, or the * character.
+integer value is negative, then the field will be left-adjusted.
+If the value is positive, but the
+.code <
+character is present in the width
+specifier, then the field is left adjusted.
+
+.meIP < precision
+The precision specifier is introduced by a leading comma. If this comma appaers
+immediately after the directive's
+.code ~
+character, then it means that
+.meta width
+is being omitted; there is only a precision field.
+
+The precision specifier may begin with these optional characters:
+.coIP 0
+(the "leading zero flag"),
+.coIP +
+(print a sign for positive values")
+.IP space
+(print a space in place of a positive sign).
+
+The precision specifier itself is either a decimal integer that does not
+begin with a zero digit, or the
+.code *
+character.
The precision field's components have a meaning which depends on the type of
object printed and the conversion specifier.
@@ -12988,33 +20393,60 @@ a leading positive or negative sign must be printed, then it is placed before
leading zeros, or after leading spaces, as the case may be.
For floating-point values, the meaning of the precision value depends on which
-specific conversion specifier (f, e, a or s) is used. The details are
+specific conversion specifier
+.cod1 ( f ,
+.codn e ,
+.code a
+or
+.codn s )
+is used. The details are
documented in the description of each of these, below. The leading zero flag is
ignored for floating-point values regardless of the conversion specifier.
-For integer or floating-point arguments, if the precision specifier has a + sign
-among the special characters, then a + sign is printed for positive numbers. If
-the precision specifier has a leading space instead of a + sign, then the +
+For integer or floating-point arguments, if the precision specifier has a
+.code +
+sign
+among the special characters, then a
+.code +
+sign is printed for positive numbers. If
+the precision specifier has a leading space instead of a
+.code +
+sign, then the
+.ocde +
sign is rendered as a space for positive numbers. If there is no leading space
-or +, then a sign character is omitted for positive numbers. Negative
-numbers are unconditionally prefixed with a - sign.
+or
+.codn + ,
+then a sign character is omitted for positive numbers. Negative
+numbers are unconditionally prefixed with a
+.code -
+sign.
For all other objects, the precision specifies the maximum number of characters
to print. The object's printed representation is crudely truncated at that
number of characters.
+.RE
-.TP
-Format directives:
-
-Format directives are case sensitive, so that for example ~x and ~X have a
-different effect, and ~A doesn't exist whereas ~a does. They are:
-
-.IP a
-Prints any object in an aesthetic way, as if by the pprint function.
+.TP* "Format directives:"
+.RS
+Format directives are case sensitive, so that for example
+.code ~x
+and
+.code ~X
+have a
+different effect, and
+.code ~A
+doesn't exist whereas
+.code ~a
+does. They are:
+
+.coIP a
+Prints any object in an aesthetic way, as if by the
+.code pprint
+function.
The aesthetic notation violates read-print consistency: this notation
is not necessarily readable if it is implanted in TXR source code.
The field width specifier is honored, including the left-right adjustment
-semantics.
+semantics.
When this specifier is used for floating-point values, the precision specifies
the maximum number of total significant figures, which do not include any
@@ -13022,39 +20454,66 @@ digits in the exponent, if one is printed. Numbers are printed in exponential
notation if their magnitude is small, or else if their exponent exceeds their
precision. (If the precision is not specified, then it defaults to the
system-dependent number of digits in a floating point value, derived from the C
-language DBL_DIG constant.) Floating point values which are integers are
-printed without a trailing .0 (point zero).
-
-.IP s
+language
+.code DBL_DIG
+constant.) Floating point values which are integers are
+printed without a trailing
+.code .0
+(point zero).
+
+.coIP s
Prints any object in a standard way, as if by the print function. Objects for
which read-print consistency is possible are printed in a way such that
if their notation is implanted in TXR source, they are readable.
The field width specifier is honored, including the left-right adjustment
-semantics. The precision field is treated very similarly to the ~a
+semantics. The precision field is treated very similarly to the
+.code ~a
format directive, except that non-exponentiated floating point numbers that
-would be mistaken for integers include a trailing ".0" for the sake read-print
+would be mistaken for integers include a trailing
+.code .0
+for the sake of read-print
consistency. Objects truncated by precision may not have read-print
consistency. For instance, if a string object is truncated, it loses its
trailing closing quote, so that the resulting representation is no longer
a properly formed string object.
-.IP x
+.coIP x
Requires an argument of character or integer type. The integer value or
character code is printed in hexadecimal, using lower-case letters
-for the digits "a" through "f". Width and precision semantics
-are as described for the "a" format directive, for integers.
-
-.IP X
-Like the "x" directive, but the digits "a" through "f" are rendered
-in upper case.
-
-.IP o
-Like the "x" directive, but octal is used instead of hexadecimal.
-
-.IP f
-The "f" directive prints numbers in a fixed point decimal notation, with
+for the digits
+.code a
+through
+.codn f .
+Width and precision semantics
+are as described for the
+.code a
+format directive, for integers.
+
+.coIP X
+Like the
+.code x
+directive, but the hexadecimal digits
+.code a
+through
+.code f
+are rendered in upper case.
+
+.coIP o
+Like the
+.code x
+directive, but octal is used instead of hexadecimal.
+
+.coIP f
+The
+.code f
+directive prints numbers in a fixed point decimal notation, with
a fixed number of digits after the decimal point. It requires a numeric
-argument. (Unlike "x", "X" and "o", characters are not permitted).
+argument. (Unlike
+.codn x ,
+.code X
+and
+.codn o ,
+it does not allow an argument of character type).
The precision specifier gives the number of digits past the decimal point.
The number is rounded off to the specified precision, if necessary.
Furthermore, that many digits are always printed, regardless of the actual
@@ -13063,249 +20522,313 @@ is three: three digits past the decimal point. A precision of zero means no
digits pas the decimal point, and in this case the decimal point is suppressed
(regardless of whether the numeric argument is floating-point or integer).
-.IP e
-The "e" directive prints numbers in exponential notation. It requires
-a numeric argument. (Unlike "x", "X" and "o", characters are not permitted).
+.coIP e
+The
+.code e
+directive prints numbers in exponential notation. It requires
+a numeric argument. (Unlike
+.codn x ,
+.code X
+and
+.codn o ,
+it does not allow an argument of character type).
The precision specifier gives the number of digits past the decimal point
printed in the exponential notation, not counting the digits in the exponent.
Exactly that many digits are printed, regardless of the precision of the
number. If the precision is omitted, then the number of digits after the
decimal point is three. If the precision is zero, then a decimal portion is
truncated off entirely, including the decimal point.
+.RE
.PP
-.SS Functions print, pprint, prinl, pprinl, tostring, tostringp
-
-.TP
-Syntax:
-
- (print <obj> [<stream>])
- (pprint <obj> [<stream>])
- (prinl <obj> [<stream>])
- (pprinl <obj> [<stream>])
- (tostring <obj>)
- (tostringp <obj>)
-
-.TP
-Description:
-
-The print and pprint functions render a printed character representation of the
-<obj> argument into <stream>. If a stream argument is not supplied, then
-the destination is the stream currently stored in the *stdout*
-variable. The print function renders in a way which strives for read-print
+.coNP Functions @, print @, pprint @, prinl @, pprinl @ tostring and @ tostringp
+.synb
+.mets (print < obj <> [ stream ])
+.mets (pprint < obj <> [ stream ])
+.mets (prinl < obj <> [ stream ])
+.mets (pprinl < obj <> [ stream ])
+.mets (tostring << obj )
+.mets (tostringp << obj )
+.syne
+.desc
+The
+.code print
+and
+.code pprint
+functions render a printed character representation of the
+.meta obj
+argument into
+.metn stream .
+If a stream argument is not supplied, then
+the destination is the stream currently stored in the
+.code *stdout*
+variable. The
+.code print
+function renders in a way which strives for read-print
consistency: an object is printed in a notation which is recognized as
a similar object of the same kind when it appears in TXR source code.
-The pprint function ("pretty print") does not strive for read-print consistency.
+The
+.code pprint
+function ("pretty print") does not strive for read-print consistency.
For instance it prints a string object simply by dumping its characters, rather
than by adding the surrounding quotes and rendering escape syntax for
-special characters. Both functions return <obj>.
-
-The prinl and pprinl functions are like print and pprint, except
-that they issue a newline character after printing the object.
-These functions also return <obj>.
-
-The tostring and tostringp functions are like print and pprint, but
-they do not accept a stream argument, instead printing to a freshly
-instantiated string stream, and returning the resulting string.
-
-The following equivalences hold between calls to the format function
-and calls to these functions:
-
+special characters. Both functions return
+.metn obj .
+
+The
+.code prinl
+and
+.code pprinl
+functions are like
+.code print
+and
+.codn pprint ,
+except that they issue a newline character after printing the object.
+These functions also return
+.metn obj .
+
+The
+.code tostring
+and
+.code tostringp
+functions are like
+.code print
+and
+.codn pprint ,
+but they do not accept a stream argument. Instead they print to a freshly
+instantiated string stream, and return the resulting string.
+
+The following equivalences hold between calls to the
+.code format
+function and calls to the above functions:
+
+.cblk
(format stream "~s" obj) <--> (print obj stream)
(format t "~s" obj) <--> (print obj)
(format t "~s\en" obj) <--> (prinl obj)
(format nil "~s" obj) <--> (tostring obj)
-
-For pprint, tostringp and pprinl, the equivalence is produced by using "~a" in
-format rather than "~s".
+.cble
+
+For
+.codn pprint ,
+.code tostringp
+and
+.codn pprinl ,
+the equivalence is produced by using
+.code ~a
+in format rather than
+.codn ~s .
Note: for characters, the print function behaves as follows: most control
-characters in the Unicode C0 and C1 range are rendered using the #\ex notation,
-using two hex digits. Codes in the range D800 to DFFF, and the codes
-FFFE and FFFF are printed in the #\exNNNN with four hexadecimal digits, and
+characters in the Unicode
+.code C0
+and
+.code C1
+range are rendered using the
+.code #\ex
+notation,
+using two hex digits. Codes in the range
+.code D800
+to
+.codn DFFF ,
+and the codes
+.code FFFE
+and
+.code FFFF
+are printed in the
+.code #\exNNNN
+with four hexadecimal digits, and
character above this range are printed using the same notation, but with six
-hexadecimal digits. Certain characters in the C0 range are printed using
-their names such as #\enul and #\ereturn, which are documented
-in the Character Literals section not far from the start of this document.
-The DC00 character is printed as #\epnul. All other characters are printed as
-#\e<char>, where <char> is the actual character.
+hexadecimal digits. Certain characters in the
+.code C0
+range are printed using
+their names such as
+.code #\enul
+and
+.codn #\ereturn ,
+which are documented
+in the Character Literals section.
+The
+.code DC00
+character is printed as
+.codn #\epnul .
+All other characters are printed as
+.cblk
+.meti >> #\e char
+.cble
+where
+.meta char
+is the actual character.
Caution: read-print consistency is affected by trailing material. If additional
digits are printed immediately after a number without intervening whitespace,
-they extend that number. If hex digits are printed after the character x,
-which is rendered as #\ex, they look like a hex character code.
-
-.SS Function streamp
-
-.TP
-Syntax:
-
- (streamp <obj>)
-
-.TP
-Description:
-
-The streamp function returns t if <obj> is any type of stream.
-Otherwise it returns nil.
-
-.SS Function real-time-stream-p
-
-.TP
-Syntax:
-
- (real-time-stream-p <obj>)
-
-.TP
-Description:
-
-The real-time-streamp-p function returns t if <obj> is a stream marked as
-"real-time". If <obj> is not a stream, or not a stream marked as "real-time",
-then it returns nil.
-
-Note: the expression (real-time-stream-p S) is almost like
-(stream-get-prop S :real-time), except the latter requires S to be a stream.
+they extend that number. If hex digits are printed after the character
+.codn x ,
+which is rendered as
+.codn #\ex ,
+they look like a hex character code.
+
+.coNP Function @ streamp
+.synb
+.mets (streamp << obj )
+.syne
+.desc
+The
+.code streamp
+function returns
+.code t
+if
+.meta obj
+is any type of stream. Otherwise it returns
+.codn nil .
+
+.coNP Function @ real-time-stream-p
+.synb
+.mets (real-time-stream-p << obj )
+.syne
+.desc
+The
+.code real-time-streamp-p
+function returns
+.code t
+if
+.meta obj
+is a stream marked as
+"real-time". If
+.meta obj
+is not a stream, or not a stream marked as "real-time",
+then it returns
+.codn nil .
Only certain kinds of streams accept the real-time attribute: file streams and
tail streams. This attribute controls the semantics of the application of
-lazy-stream-cons to the stream. For a real-time stream, lazy-stream-cons
+.code lazy-stream-cons
+to the stream. For a real-time stream,
+.code lazy-stream-cons
returns a stream with "naive" semantics which returns data as soon as it is
-available, at the cost of generating spurious nil item when the stream
-terminates. The application has to recognize and discard that nil item.
+available, at the cost of generating spurious
+.code nil
+item when the stream
+terminates. The application has to recognize and discard that
+.code nil
+item.
The ordinary lazy streams read ahead by one line and suppress this extra
item, so their representation is more accurate.
-Streams connected to TTY devices (devices which for which the isatty function
-reports true) are marked as real-time. This is only supported on platforms that
-have an isatty function.
-
-
-.SS Function make-string-input-stream
-
-.TP
-Syntax:
-
- (make-string-input-stream <string>)
-
-.TP
-Description:
+Streams connected to TTY devices (devices which for which the
+.code isatty
+POSIX function reports true) are automatically marked as real-time. This is
+only supported on platforms that have an
+.code isatty
+function.
+.coNP Function @ make-string-input-stream
+.synb
+.mets (make-string-input-stream << string )
+.syne
+.desc
This function produces an input stream object. Character read operations on the
-stream object read successive characters from <string>. Output
-operations and byte operations are not supported.
-
-.SS Function make-string-byte-input-stream
-
-.TP
-Syntax:
-
- (make-string-byte-input-stream <string>)
-
-.TP
-Description:
-
+stream object read successive characters from
+.metn string .
+Output operations and byte operations are not supported.
+
+.coNP Function @ make-string-byte-input-stream
+.synb
+.mets (make-string-byte-input-stream << string )
+.syne
+.desc
This function produces an input stream object. Byte read operations on
this stream object read successive byte values obtained by encoding
-<string> into UTF-8. Character read operations are not supported, and neither
+.meta string
+into UTF-8. Character read operations are not supported, and neither
are output operations.
-.SS Function make-string-output-stream
-
-.TP
-Syntax:
-
+.coNP Function @ make-string-output-stream
+.synb
(make-string-output-stream)
-
-.TP
-Description:
-
+.syne
+.desc
This function, which takes no arguments, creates a string output stream.
Data sent to this stream is accumulated into a string object.
-String output streams supports both character and byte output operations.
+String output streams supports both character and byte output operations.
Bytes are assumed to represent a UTF-8 encoding, and are decoded in order
-to form characters which are stored into the string.
+to form characters which are stored into the string.
If an incomplete UTF-8 code is output, and a character output operation then
takes place, that code is assumed to be terminated and is decoded as invalid
bytes. The UTF-8 decoding machine is reset and ready for the start of a new
code.
-The get-string-from-stream function is used to retrieve the accumulated
-string.
+The
+.code get-string-from-stream
+function is used to retrieve the accumulated string.
If the null character is written to a string output stream, either via
a character output operation or as a byte operation, the resulting string
will appear to be prematurely terminated. TXR strings cannot contain null
bytes.
-.SS Function get-string-from-stream
-
-.TP
-Syntax:
-
- (get-string-from-stream <stream>)
-
-.TP
-Description:
-
-The <stream> argument must be a string output stream. This function finalizes
+.coNP Function @ get-string-from-stream
+.synb
+.mets (get-string-from-stream << stream )
+.syne
+.desc
+The
+.meta stream
+argument must be a string output stream. This function finalizes
the data sent to the stream and retrieves the accumulated character string.
-If a partial UTF-8 code has been written to <stream>, and then this
+If a partial UTF-8 code has been written to
+.metn stream ,
+and then this
function is called, the byte stream is considered complete and the partial
code is decoded as invalid bytes.
After this function is called, further output on the stream is not possible.
-.SS Function make-strlist-output-stream
-
-.TP
-Syntax:
-
+.coNP Function @ make-strlist-output-stream
+.synb
(make-strlist-output-stream)
-
-.TP
-Description:
-
-This function is closely analogous to make-string-output-stream. However,
-instead of producing a string, it produces a list of strings. The
-data is broken into multiple strings by newline characters written
-to the stream. Newline characters do not appear in the string list. Also, byte
-output operations are not supported.
-
-.SS Function get-list-from-stream
-
-.TP
-Syntax:
-
- (get-list-from-stream <stream>)
-
-.TP
-Description:
-
+.syne
+.desc
+This function is very similar to
+.codn make-string-output-stream .
+However, the stream object produced by this function does not produce a string,
+but a list of strings. The data is broken into multiple strings by newline
+characters written to the stream. Newline characters do not appear in the
+string list. Also, byte output operations are not supported.
+
+.coNP Function @ get-list-from-stream
+.synb
+.mets (get-list-from-stream << stream )
+.syne
+.desc
This function returns the string list which has accumulated inside
-a string output stream given by <stream>. The string output stream is
+a string output stream given by
+.metn stream .
+The string output stream is
finalized, so that further output is no longer possible.
-.SS Function close-stream
-
-.TP
-Syntax:
-
- (close-stream <stream> [<throw-on-error-p>])
-
-.TP
-Description:
-
-The close-stream function performs a close operation on <stream>,
+.coNP Function @ close-stream
+.synb
+.mets (close-stream < stream <> [ throw-on-error-p ])
+.syne
+.desc
+The
+.code close-stream
+function performs a close operation on
+.metn stream ,
whose meaning is depends on the type of the stream. For some types of streams,
such as string streams, it does nothing. For streams which are connected
to operating system files or devices, will perform a close of the underlying
file descriptor, and dissociate that descriptor from the stream. Any buffered
data is flushed first.
-The function returns a boolean true value if the close has occurred without
-errors, otherwise nil.
+.code close-stream
+returns a boolean true value if the close has occurred without
+errors, otherwise
+.codn nil .
For most streams, "without errors" means that any buffered output data is
flushed successfully.
@@ -13317,263 +20840,345 @@ as is the inability to retrieve the termination status, as well as the situation
that the process continues running in spite of the close attempt.
Detecting these situations is platform specific.
-If the <throw-on-error-p> argument is specified, and isn't nil, then the
+If the
+.meta throw-on-error-p
+argument is specified, and isn't
+.codn nil ,
+then the
function throws an exception if an error occurs during the close operation
-instead of returning nil.
-
-.SS Functions get-line, get-char and get-byte
-
-.TP
-Syntax:
-
- (get-line [<stream>])
- (get-char [<stream>])
- (get-byte [<stream>])
-
-.TP
-Description:
-
-These fundamental stream functions perform input. The <stream> argument
+instead of returning
+.codn nil .
+
+.coNP Functions @, get-line @ get-char and @ get-byte
+.synb
+.mets (get-line <> [ stream ])
+.mets (get-char <> [ stream ])
+.mets (get-byte <> [ stream ])
+.syne
+.desc
+These fundamental stream functions perform input. The
+.meta stream
+argument
is optional. If it is specified, it should be an input stream which supports
-the given operation. If it is not specified, then the *stdin*
+the given operation. If it is not specified, then the
+.code *stdin*
stream is used.
-The get-char function pulls a character from a stream which supports character
-input. Streams which support character input also support the get-line
+The
+.code get-char
+function pulls a character from a stream which supports character
+input. Streams which support character input also support the
+.code get-line
function which extracts a line of text delimited by the end of the stream or a
newline character and returns it as a string. (The newline character does not
-appear in the string which is returned).
+appear in the string which is returned).
Character input from streams based on bytes requires UTF-8 decoding, so that
get-char actually may read several bytes from the underlying low level
operating system stream.
-The get-byte function bypasses UTF-8 decoding and reads raw bytes from
+The
+.code get-byte
+function bypasses UTF-8 decoding and reads raw bytes from
any stream which supports byte input. Bytes are represented as integer
values in the range 0 to 255.
Note that if a stream supports both byte input and character input, then mixing
the two operations will interfere with the UTF-8 decoding.
-These functions return nil when the end of data is reached. Errors are
+These functions return
+.code nil
+when the end of data is reached. Errors are
represented as exceptions.
-See also: get-lines
-
-.SS Function get-string
-
-.TP
-Syntax:
-
- (get-string [<stream> [<count>]])
-
-.TP
-Description:
-
-The get-string function reads characters from a stream, and assembles them into
-a string, which is returned. If the <stream> argument is omitted, then the
-*stdin* stream is used.
+See also:
+.code get-lines
+
+.coNP Function @ get-string
+.synb
+.mets (get-string >> [ stream <> [ count ]])
+.syne
+.desc
+The
+.code get-string
+function reads characters from a stream, and assembles them into
+a string, which is returned. If the
+.meta stream
+argument is omitted, then the
+.code *stdin*
+stream is used.
-If the <count> argument is missing, then all of the characters from the
+If the
+.meta count
+argument is missing, then all of the characters from the
stream are read and assembled into a string.
-If present, the <count> argument should be a positive integer indicating
+If present, the
+.meta count
+argument should be a positive integer indicating
a limit on how many characters to read. The returned string will be no
-longer than <count>, but may be shorter.
-
-.SS Functions unget-char and unget-byte
-
-.TP
-Syntax:
-
- (unget-char <char> [<stream>])
- (unget-byte <byte> [<stream>])
-
-.TP
-Description:
-
-These character put back, into a stream, a character or byte which was
+longer than
+.metn count ,
+but may be shorter.
+
+.coNP Functions @ unget-char and @ unget-byte
+.synb
+.mets (unget-char < char <> [ stream ])
+.mets (unget-byte < byte <> [ stream ])
+.syne
+.desc
+These functions put back, into a stream, a character or byte which was
previously read. The character or byte must match the one which was most
-recently read. If the <stream> argument is omitted, then the *stdin*
+recently read. If the
+.meta stream
+argument is omitted, then the
+.code *stdin*
stream is used.
If the operation succeeds, the byte or character value is returned.
-A nil return indicates that the operation is unsupported.
+A
+.code nil
+return indicates that the operation is unsupported.
Some streams do not support these operations; some support
-only one of them. In general, if a stream supports get-char,
-it supports unget-char, and likewise for get-byte and unget-byte.
+only one of them. In general, if a stream supports
+.codn get-char ,
+it supports
+.codn unget-char ,
+and likewise for
+.code get-byte
+and
+.codn unget-byte .
Space is available for only one character or byte of pushback.
-Pushing both a byte and a character, in either order, is also unsupported.
+Pushing both a byte and a character, in either order, is also unsupported.
Pushing a byte and then reading a character, or pushing a character and
-reading a byte, are also unsupported mixtures of operations.
+reading a byte, are unsupported mixtures of operations.
If the stream is binary, then pushing back a byte decrements its position,
except if the position is already zero. At that point, the position becomes
indeterminate.
-.SS Functions put-string, put-line, put-char and put-byte
-
-.TP
-Syntax:
-
- (put-string <string> [<stream>])
- (put-line [<string> [<stream>]])
- (put-char <char> [<stream>])
- (put-byte <byte> [<stream>])
-
-.TP
-Description:
-
-These functions perform output on an output stream. The <stream> argument
+.coNP Functions @, put-string @, put-line @ put-char and @ put-byte
+.synb
+.mets (put-string < string <> [ stream ])
+.mets (put-line >> [ string <> [ stream ]])
+.mets (put-char < char <> [ stream ])
+.mets (put-byte < byte <> [ stream ])
+.syne
+.desc
+These functions perform output on an output stream. The
+.meta stream
+argument
must be an output stream which supports the given operation. If it is omitted,
-then *stdout* is used.
-
-The put-char function writes a character given by <char> to a stream. If the
+then
+.code *stdout*
+is used.
+
+The
+.code put-char
+function writes a character given by
+.code char
+to a stream. If the
stream is based on bytes, then the character is encoded into UTF-8 and multiple
-bytes are written. Streams which support put-char also support put-line, and
-put-string.
-
-The put-string function writes the characters of a string out to
-the stream as if by multiple calls to put-char. The <string> argument
+bytes are written. Streams which support
+.code put-char
+also support put-line, and
+.codn put-string .
+
+The
+.code put-string
+function writes the characters of a string out to
+the stream as if by multiple calls to put-char. The
+.meta string
+argument
may be a symbol, in which case its name is used as the string.
-The put-line function is like put-string, but also writes an additional newline
-character. The string is optional in put-line, and defaults to the empty
-string.
-
-The put-byte function writes a raw byte given by the <byte> argument
-to <stream>, if <stream> supports a byte write operation. The byte
+The
+.code put-line
+function is like
+.codn put-string ,
+but also writes an additional newline
+character. The string is optional in
+.codn put-line ,
+and defaults to the empty string.
+
+The
+.code put-byte
+function writes a raw byte given by the
+.meta byte
+argument
+to
+.metn stream ,
+if
+.meta stream
+supports a byte write operation. The byte
value is specified as an integer value in the range 0 to 255.
-.SS Functions put-strings and put-lines
-
-.TP
-Syntax:
-
- (put-strings <sequence> [<stream>]])
- (put-lines <sequence> [<stream>]])
-
-.TP
-Description:
-
-These functions assume <sequence> to be a sequence of strings, or of
+.coNP Functions @ put-strings and @ put-lines
+.synb
+.mets (put-strings < sequence <> [ stream ]])
+.mets (put-lines < sequence <> [ stream ]])
+.syne
+.desc
+These functions assume
+.meta sequence
+to be a sequence of strings, or of
symbols, or a mixture thereof. These strings are sent to the stream. The
-<stream> argument must be an output stream. If it is omitted, then *stdout* is
-used.
-
-The put-strings function iterates over <sequence> and writes each element
-to the stream as if using the put-string function.
-
-The put-lines function iterates over <sequence> and writes each element
-to the stream as if using the put-line function.
-
-Both functions return t.
-
-.SS Function flush-stream
-
-.TP
-Syntax:
+.meta stream
+argument must be an output stream. If it is omitted, then
+.code *stdout*
+is used.
+
+The
+.code put-strings
+function iterates over
+.meta sequence
+and writes each element
+to the stream as if using the
+.code put-string
+function.
- (flush-stream <stream>)
+The
+.code put-lines
+function iterates over
+.code sequence
+and writes each element
+to the stream as if using the
+.code put-line
+function.
-.TP
-Description:
+Both functions return
+.codn t .
+.coNP Function @ flush-stream
+.synb
+.mets (flush-stream << stream )
+.syne
+.desc
This function is meaningful for output streams which accumulate data
which is passed on to the operating system in larger transfer units.
-Calling this function causes all accumulated data inside <stream> to be passed
+Calling
+.code flush-stream
+causes all accumulated data inside
+.meta stream
+to be passed
to the operating system. If called on streams for which this function is not
meaningful, it does nothing.
-.SS Function seek-stream
-
-.TP
-Syntax:
-
- (seek-stream <stream> <offset> <whence>)
-
-.TP
-Description:
-
-The seek-stream function is meaningful for file streams. It changes the
-current read/write position within <stream>. It can also be used
-to determine the current position: see the notes about the
+.coNP Function @ seek-stream
+.synb
+.mets (seek-stream < stream < offset << whence )
+.syne
+.desc
+The
+.code seek-stream
+function is meaningful for file streams. It changes the
+current read/write position within
+.metn stream .
+It can also be used to determine the current position: see the notes about the
return value below.
-The <offset> argument is a positive or negative integer which gives a
-displacement that is measured from the point identified by the <whence>
+The
+.meta offset
+argument is a positive or negative integer which gives a
+displacement that is measured from the point identified by the
+.meta whence
argument.
Note that for text files, there isn't necessarily a 1:1 correspondence between
characters and positions due to line-ending conversions and conversions
to and from UTF-8.
-The <whence> argument is one of three keywords: :from-start, :from-current
+The
+.meta whence
+argument is one of three keywords: :from-start, :from-current
and :from-end. These denote the start of the file, the current position
and the end of the file.
-If <offset> is zero, and <whence> is :from-current, then
-seek-stream returns the current absolute position within the
+If
+.meta offset
+is zero, and
+.meta whence
+is
+.codn :from-current ,
+then
+.code seek-stream
+returns the current absolute position within the
stream, if it can successfully obtain it. Otherwise, it
-returns t if it is successful.
+returns
+.code t
+if it is successful.
If a character has been successfully put back into a text stream with
-unget-char and is still pending, then the position value is unspecified. If a
-byte has been put back into a binary stream with unget-byte, and the previous
-position wasn't zero, then the position is decremented by one.
-
-On failure, it throws an exception of type stream-error.
-
-.SS Functions stream-get-prop and stream-set-prop
-
-.TP
-Syntax:
-
- (stream-get-prop <stream> <indicator>)
- (stream-set-prop <stream> <indicator> <value>)
-
-.TP
-Description:
-
+.code unget-char
+and is still pending, then the position value is unspecified. If a
+byte has been put back into a binary stream with
+.codn unget-byte ,
+and the previous position wasn't zero, then the position is decremented by one.
+
+On failure, it throws an exception of type
+.codn stream-error .
+
+.coNP Functions @ stream-get-prop and @ stream-set-prop
+.synb
+.mets (stream-get-prop < stream << indicator )
+.mets (stream-set-prop < stream < indicator << value )
+.syne
+.desc
These functions get and set properties on a stream. Only certain properties
are meaningful with certain kinds of streams, and the meaning depends on
the stream. If two or more stream types support a property of the same name, it
is expected that the property has the same or very similar meaning for both
-streams to the maximum extent that similarity is possible possible.
+streams to the maximum extent that similarity is possible.
-The stream-set-prop function sets a property on a stream. The <indicator>
+The
+.code stream-set-prop
+function sets a property on a stream. The
+.meta indicator
argument is a symbol, usually a keyword symbol, denoting the property,
-and <value> is the property value. If the stream understands and accepts the
-property, the function returns t. Otherwise it returns nil.
-
-The stream-get-prop function inquires about the value of a property on a
+and
+.meta value
+is the property value. If the stream understands and accepts the
+property, the function returns
+.codn t .
+Otherwise it returns
+.codn nil .
+
+The
+.code stream-get-prop
+function inquires about the value of a property on a
stream. If the stream understands the property, then it returns its current
value. If the stream does not understand a property, nil is returned, which is
-also returned if the property exists, but its value happens to be nil.
+also returned if the property exists, but its value happens to be
+.codn nil .
Properties are currently used for marking certain streams as "real-time" (see
-the stream-real-time-p function above), and also for setting the priority at
-which messages are reported to syslog by the *stdlog* stream (see *stdlog*
+the
+.code stream-real-time-p
+function above), and also for setting the priority at
+which messages are reported to syslog by the
+.code *stdlog*
+stream (see
+.code *stdlog*
in the UNIX SYSLOG section).
-If <stream> is a catenated stream (see the function make-catenated-stream)
+If
+.meta stream
+is a catenated stream (see the function
+.codn make-catenated-stream )
then these functions transparently operate on the current head stream of the
catenation.
-.SS Function make-catenated-stream
-
-.TP
-Syntax:
-
- (make-catenated-stream <stream>*)
-
-.TP
-Description
-
-The make-catenated-stream function takes zero or more arguments which
+.coNP Function @ make-catenated-stream
+.synb
+.mets (make-catenated-stream << stream *)
+.syne
+.desc
+The
+.code make-catenated-stream
+function takes zero or more arguments which
are input streams of the same type.
A catenated stream does not support seeking operations or output,
@@ -13582,16 +21187,35 @@ regardless of the capabilities of the streams in the list.
If the stream list is not empty, then the leftmost element of the
list is called the head stream.
-The get-char, get-byte, get-line, unget-char and unget-byte delegate
+The
+.codn get-char ,
+.codn get-byte ,
+.codn get-line ,
+.code unget-char
+and
+.code unget-byte
+functions delegate
to the corresponding operations on the head stream, if it exists.
-If the stream list is empty, they return nil to the caller.
-
-The a get-char, get-byte or get-line operation on the head stream yields nil,
+If the stream list is empty, they return
+.code nil
+to the caller.
+
+If the
+.codn get-char ,
+.code get-byte
+or
+.code get-line
+operation on the head stream yields
+.codn nil ,
and there are more lists in the stream, then the stream is removed from the
list, and the next stream, if any, becomes the head list. The operation is then
tried again. If any of these operations fail on the last list, it is not
removed from the list, so that a stream remains in place which can take
-the unget-char or unget-byte operations.
+the
+.code unget-char
+or
+.code unget-byte
+operations.
In this manner, the catenated streams appear to be a single stream.
@@ -13600,59 +21224,82 @@ the caller's responsibility to make sure all of the streams in the list
are compatible with the intended operations.
If the stream list is empty then an empty catenated stream is produced.
-Input operations on this stream yield nil, and the unget-char
-and unget-byte operations throw an exception.
-
-.SS Functions open-files and open-files*
-
-.TP
-Syntax:
-
- (open-files <path-list> [<alternative-stream>])
- (open-files* <path-list> [<alternative-stream>])
-
-.TP
-Description:
-
-The open-files and open-files* functions create a list of streams by invoking
-the open-file function on each element of <path-list>. These streams are turned
-into a catenated stream as if applied as arguments to make-catenated-stream.
+Input operations on this stream yield
+.codn nil ,
+and the
+.code unget-char
+and
+.code unget-byte
+operations throw an exception.
+
+.coNP Functions @ open-files and @ open-files*
+.synb
+.mets (open-files < path-list <> [ alternative-stream ])
+.mets (open-files* < path-list <> [ alternative-stream ])
+.syne
+.desc
+The
+.code open-files
+and
+.code open-files*
+functions create a list of streams by invoking
+the open-file function on each element of
+.metn path-list .
+These streams are turned
+into a catenated stream as if applied as arguments to
+.codn make-catenated-stream .
The effect is that multiple files appear to be catenated together into a single
input stream.
-If the optional <alternative-stream> argument is supplied, then if <path-list>
-is empty, that argument is returned instead of an empty catenated stream.
-
-The difference between open-files and open-files* is that open-files creates all of the
+If the optional
+.meta alternative-stream
+argument is supplied, then if
+.meta path-list
+is empty,
+.meta alternative-stream
+is returned instead of an empty catenated stream.
+
+The difference between
+.code open-files
+and
+.code open-files*
+is that
+.code open-files
+creates all of the
streams up-front. So if any of the paths cannot be opened, the operation throws.
-The open-files* variant is lazy: it creates a lazy list of streams out of the
+The
+.code open-files*
+variant is lazy: it creates a lazy list of streams out of the
path list. The streams are opened as needed: before the second stream is opened,
the program has to read the first stream to the end, and so on.
-.TP
-Example:
+.TP* Example:
Collect lines from all files that are given as arguments on the command line. If
there are no files, then read from standard input:
+.cblk
@(next @(open-files *args* *stdin*))
@(collect)
@line
@(end)
-
-.SS Function abs-path-p
-
-.TP
-Syntax:
-
- (abs-path-p <path>)
-
-.TP
-Description:
-
-The abs-path-function whether the argument <path> is an absolute path.
-If this is true, it returns t, otherwise nil.
+.cble
+
+.coNP Function @ abs-path-p
+.synb
+.mets (abs-path-p << path )
+.syne
+.desc
+The
+.code abs-path-function
+tests whether the argument
+.meta path
+is an absolute path, returning a
+.code t
+or
+.code nil
+indication.
An absolute path is a string which either begins with a slash or backslash
character, or which begins with an alphanumeric word, followed by a colon,
@@ -13660,37 +21307,38 @@ followed by a slash or backslash.
Examples of absolute paths:
+.cblk
/etc
-
c:/tmp
-
ftp://user@server
-
disk0:/home
-
Z:\eUsers
+.cble
Examples of strings which are not absolute paths.
- (the empty string)
+.cblk
+.mets < (the < empty < string)
.
abc
foo:bar/x
$:\eabc
-
-.SS Function read
-
-.TP
-Syntax:
-
- (read [<source> [<error-stream> [<error-return-value>]]])
-
-.TP
-Description:
-
-The read function converts text denoting TXR Lisp structure, into the
-corresponding data structure. The <source> argument may be either a character
-string, or a stream. If it is omitted, then *stdin* is used as the stream.
+.cble
+
+.coNP Function @ read
+.synb
+.mets (read >> [ source >> [ error-stream <> [ error-return-value ]]])
+.syne
+.desc
+The
+.code read
+function converts text denoting TXR Lisp structure, into the
+corresponding data structure. The
+.meta source
+argument may be either a character
+string, or a stream. If it is omitted, then
+.code *stdin*
+is used as the stream.
The source must provide the text representation of one complete TXR Lisp object.
@@ -13698,120 +21346,195 @@ Multiple calls to read on the same stream will extract successive objects
from the stream. To parse successive objects from a string, it is necessary
to convert it to a string stream.
-The optional <error-stream> argument can be used to specify a stream to which
+The optional
+.meta error-stream
+argument can be used to specify a stream to which
parse errors diagnostics are sent. If absent, the diagnostics are suppressed.
If there are no parse errors, the function returns the parsed data
-structure. If there are parse errors, and the <error-return-value> parameter is
-present, its value is returned. If the <error-return-value> parameter
-is not present, then an exception of type syntax-error is thrown.
-
-.SH FILESYSTEM ACCESS
-
-.SS Function stat
-
-.TP
-Syntax:
-
- (stat <path>)
-
-.TP
-Description:
+structure. If there are parse errors, and the
+.meta error-return-value
+parameter is
+present, its value is returned. If the
+.meta error-return-value
+parameter
+is not present, then an exception of type
+.code syntax-error
+is thrown.
-The stat function inquires the filesystem about the existence of an object
-denoted by the string <path>. If the object is not found or cannot be
+.SS* Filesystem Access
+.coNP Function @ stat
+.synb
+.mets (stat << path )
+.syne
+.desc
+The
+.code stat
+function inquires the filesystem about the existence of an object
+denoted by the string
+.metn path .
+If the object is not found or cannot be
accessed, an exception is thrown.
-Otherwise information is retrieved about the object. The information takes the
+Otherwise, information is retrieved about the object. The information takes the
form of a property list in which keyword symbols denote numerous properties.
-An example such property list is (:dev 2049 :ino 669944 :mode 16832 :nlink 23
-:uid 500 :gid 500 :rdev 0 :size 12288 :blksize 4096 :blocks 24 :atime
-1347933533 :mtime 1347933534 :ctime 1347933534)
+An example such property list is:
-These properties correspond to the similarly-named entries of the struct stat
-structure in POSIX. For instance, the :dev property has the same value
-as the st_dev field.
+.cblk
+ (:dev 2049 :ino 669944 :mode 16832 :nlink 23
+ :uid 500 :gid 500 :rdev 0
+ :size 12288 :blksize 4096 :blocks 24
+ :atime 1347933533 :mtime 1347933534 :ctime 1347933534)
+.cble
-.SS Special variables s-ifmt s-iflnk s-ifreg s-ifblk ... s-ixoth
+These properties correspond to the similarly-named entries of the
+.code struct stat
+structure in POSIX. For instance, the
+.code :dev
+property has the same value as the
+.code st_dev
+field.
-The following variables exist, having integer values. These are bitmasks
-which can be applied against the value given by the :mode property
-in the property list returned by the function stat: s-ifmt, s-ifsock, s-iflnk,
-s-ifreg, s-ifblk, s-ifdir, s-ifchr, s-ififo, s-isuid, s-isgid, s-isvtx,
-s-irwxu, s-irusr, s-iwusr, s-ixusr, s-irwxg, s-irgrp, s-iwgrp, s-ixgrp,
-s-irwxo, s-iroth, s-iwoth and s-ixoth.
+.coNP Special variables @, s-ifmt @, s-iflnk @, s-ifreg @, s-ifblk ... , @ s-ixoth
-These variables correspond to the C constants S_IFMT, S_IFLNK, S_IFREG
+The following variables exist, having integer values. These are bitmasks
+which can be applied against the value given by the
+.code :mode
+property
+in the property list returned by the function stat:
+.codn s-ifmt ,
+.codn s-ifsock ,
+.codn s-iflnk ,
+.codn s-ifreg ,
+.codn s-ifblk ,
+.codn s-ifdir ,
+.codn s-ifchr ,
+.codn s-ififo ,
+.codn s-isuid ,
+.codn s-isgid ,
+.codn s-isvtx ,
+.codn s-irwxu ,
+.codn s-irusr ,
+.codn s-iwusr ,
+.codn s-ixusr ,
+.codn s-irwxg ,
+.codn s-irgrp ,
+.codn s-iwgrp ,
+.codn s-ixgrp ,
+.codn s-irwxo ,
+.codn s-iroth ,
+.code s-iwoth
+and
+.codn s-ixoth .
+
+These variables correspond to the C language constants from POSIX:
+.codn S_IFMT ,
+.codn S_IFLNK ,
+.code S_IFREG
and so forth.
-The logtest function can be used to test these against values of mode.
-For example (logtest mode s-irgrp) tests for the group read permission.
-
-.SS Function open-directory
-
-.TP
-Syntax:
-
- (open-directory <path>)
-
-.TP
-Description:
-
-The open-directory function tries to create a stream which reads the
-directory given by the string argument <path>. If a filesystem object exists
+The
+.code logtest
+function can be used to test these against values of mode.
+For example
+.code (logtest mode s-irgrp)
+tests for the group read permission.
+
+.coNP Function @ open-directory
+.synb
+.mets (open-directory << path )
+.syne
+.desc
+The
+.code open-directory
+function tries to create a stream which reads the
+directory given by the string argument
+.metn path .
+If a filesystem object exists
under the path, is accessible, and is a directory, then the function
returns a stream. Otherwise, a file error exception is thrown.
The resulting stream supports the get-line operation. Each call to the
-get-line operation retrieves a string representing the next directory
-entry. The value nil is returned when there are no more directory entries.
-The . and .. entries in Unix filesystems are not skipped.
-
-.SS Function open-file
-
-.TP
-Syntax:
-
- (open-file <path> [<mode-string>])
-
-.TP
-Description:
-
-The open-file function creates a stream connected to the file
-which is located at the given <path>, which is a string.
-
-The <mode-string> argument is a string which uses the same
-conventions as the mode argument of the C language fopen function.
+.code get-line
+operation retrieves a string representing the next directory
+entry. The value
+.code nil
+is returned when there are no more directory entries.
+The
+.code .
+and
+.code ..
+entries in Unix filesystems are not skipped.
+
+.coNP Function @ open-file
+.synb
+.mets (open-file < path <> [ mode-string ])
+.syne
+.desc
+The
+.code open-file
+function creates a stream connected to the file
+which is located at the given
+.metn path ,
+which is a string.
+
+The
+.meta mode-string
+argument is a string which uses the same
+conventions as the mode argument of the C language
+.code fopen
+function.
The mode string determines whether the stream is an input stream
-or output stream. Note that the "b" mode is not supported.
+or output stream. Note that the
+.str b
+mode is not supported.
Whether a stream is text or binary depends on which operations
are invoked on it.
-If the <mode-string> argument is omitted, the mode "r" is used.
-
-.SS Function open-tail
-
-.TP
-Syntax:
-
- (open-tail <path> [ [<mode-string>] <seek-to-end-p> ])
-
-.TP
-Description:
-
-The open-tail function creates a tail stream connected to the file which is
-located at the given <path>. The <mode-string> argument is a string which uses
-the same conventions as the mode argument of the C language fopen function.
-If it is missing, it defaults to "r". Note that the "b" mode is not supported.
+If the
+.meta mode-string
+argument is omitted, mode
+.str r
+is used.
+
+.coNP Function @ open-tail
+.synb
+.mets (open-tail < path <> [[ mode-string ] << seek-to-end-p ])
+.syne
+.desc
+The
+.code open-tail
+function creates a tail stream connected to the file which is
+located at the given
+.metn path .
+The
+.meta mode-string
+argument is a string which uses
+the same conventions as the mode argument of the C language
+.code fopen
+function.
+If it is missing, it defaults to
+.strn r .
+Note that the
+.str b
+mode is not supported.
Whether a stream is text or binary depends on which operations are invoked on
-it.
+it.
-The <seek-to-end-p> argument is a boolean which determines whether the initial
+The
+.code seek-to-end-p
+argument is a boolean which determines whether the initial
read/write position is at the start of the file, or just past the end.
-It defaults to nil. This argument only makes a difference if the file exists
-at the time open-tail is called. If the file does not exist, and is later
+It defaults to
+.codn nil .
+This argument only makes a difference if the file exists
+at the time
+.code open-tail
+is called. If the file does not exist, and is later
created, then the tail stream will follow that file from the beginning. In
-other words, <seek-to-end-p> controls whether the tail stream reads all the
+other words,
+.meta seek-to-end-p
+controls whether the tail stream reads all the
existing data in the file, if any, or whether it reads only newly added data
from approximately the time the stream is created.
@@ -13820,607 +21543,778 @@ of file. A tail stream never reports an end-of-file condition; instead
it polls the file until more data is added. Furthermore, if the file
is truncated, or replaced with a smaller file, the tail stream follows
this change: it automatically opens the smaller file and starts reading from
-the beginning (the <seek-to-end-p> flag only applies to the initial open).
+the beginning (the
+.meta seek-to-end-p
+flag only applies to the initial open).
In this manner, a tail stream can dynamically growing rotating log files.
Caveat: since a tail stream can re-open a new file which has the same
-name as the original file, it will do the wrong thing if the program
+name as the original file, it behave incorrectly if the program
changes the current working directory, and the path name is relative.
-.SS Function remove-path
-
-.TP
-Syntax:
-
- (remove-path <path>)
-
-.TP
-Description:
-
-The remove-path function tries to remove the filesystem object named
-by <path>, which may be a file, directory or something else.
-
-If successful, it returns t.
-
-A failure to remove the object results in an exception of type file-error.
-
-.SS Function rename-path
-
-.TP
-Syntax:
-
- (rename-path <from-path> <to-path>)
-
-.TP
-Description:
-
-The remove-path function tries to rename filesystem path <from-path>, which may
-refer to a file, directory or something else, to the path <to-path>.
-
-If successful, it returns t.
-
-A failure to rename path results in an exception of type file-error.
-
-
-.TP
-Description:
-
-.SH COPROCESSES
-
-.SS Functions open-command, open-process
-
-.TP
-Syntax:
-
- (open-command <system-command> [<mode-string>])
- (open-process <program> <mode-string> [<argument-strings>])
-
-.TP
-Description:
-
+.coNP Function @ remove-path
+.synb
+.mets (remove-path << path )
+.syne
+.desc
+The
+.code remove-path
+function tries to remove the filesystem object named
+by
+.metn path ,
+which may be a file, directory or something else.
+
+If successful, it returns
+.codn t .
+
+A failure to remove the object results in an exception of type
+.codn file-error .
+
+.coNP Function @ rename-path
+.synb
+.mets (rename-path < from-path << to-path )
+.syne
+.desc
+The
+.code remove-path
+function tries to rename filesystem path
+.metn from-path ,
+which may refer to a file, directory or something else, to the path
+.metn to-path .
+
+If successful, it returns
+.codn t .
+
+A failure results in an exception of type
+.codn file-error .
+
+.SS* Coprocesses
+.coNP Functions @ open-command and @ open-process
+.synb
+.mets (open-command < system-command <> [ mode-string ])
+.mets (open-process < program < mode-string <> [ argument-string *])
+.syne
+.desc
These functions spawn external programs which execute concurrently
with the TXR program. Both functions return a unidirectional stream for
communicating with these programs: either an output stream, or an input
-stream, depending on the contents of <mode-string>.
-
-In open-command, the <mode-string> argument is optional, defaulting to
-the value "r" if it is missing.
+stream, depending on the contents of
+.metn mode-string .
-The open-command function accepts, via the <system-command> string parameter, a
+In
+.codn open-command ,
+the
+.meta mode-string
+argument is optional, defaulting to
+the value
+.str r
+if it is missing.
+
+The
+.code open-command
+function accepts, via the
+.meta system-command
+string parameter, a
system command, which is in a system-dependent syntax. On a POSIX system, this
would be in the POSIX Shell Command Language.
-The open-process function specifies a program to invoke via the <command>
+The
+.code open-process
+function specifies a program to invoke via the
+.meta command
argument. This is subject to the operating system's search strategy.
On POSIX systems, if it is an absolute or relative path, it is treated as
such, but if it is a simple base name, then it is subject to searching
via the components of the PATH environment variable. If open-process
-is not able to find <program>, or is otherwise unable to execute
-the program, the child process will exit, using the value of errno
-as its exit status. This value can be retrieved via close-stream.
-
-The <mode-string> argument is compatible with the convention used by the POSIX
-popen function.
-
-The <argument-strings> argument is a list of strings which specifies additional
-optional arguments to be passed passed to the program. The <program> argument
-becomes the first argument, and <argument-strings> become the second and
-subsequent arguments. If <argument-strings> is omitted, it defaults to empty.
+is not able to find
+.metn program ,
+or is otherwise unable to execute
+the program, the child process will exit, using the value of the C variable
+.code errno
+as its exit status. This value can be retrieved via
+.codn close-stream .
+
+The
+.meta mode-string
+argument follows the convention used by the POSIX
+.code popen
+function.
-If a coprocess is open for writing (<mode-string> is specified as "w"), then
+The
+.meta argument-strings
+argument is a list of strings which specifies additional
+optional arguments to be passed passed to the program. The
+.meta program
+argument
+becomes the first argument, and
+.meta argument-string
+become the second and
+subsequent arguments. If
+.meta argument-strings
+is omitted, it defaults to empty.
+
+If a coprocess is open for writing
+.cblk
+.meti >> ( mode-string
+.cble
+is specified as
+.strn w ),
+then
writing on the returned stream feeds input to that program's standard input
file descriptor. Indicating the end of input is performed by closing the
stream.
-If a coprocess is open for reading (<mode-string> is specified as "r"), then
+If a coprocess is open for reading
+.cblk
+.meti >> ( mode-string
+.cble
+is specified as
+.strn r ),
+then
the program's output can be gathered by reading from the returned stream.
When the program finishes output, it will close the stream, which can be
detected as normal end of data.
If a coprocess terminates abnormally or unsuccessfully, an exception is raised.
-.SH SYMBOLS AND PACKAGES
-
-A package is an object which serves as a container of symbols.
+.SS* Symbols and Packages
+A package is an object which serves as a container of symbols.
A symbol which exists inside a package is said to be interned in that package.
A symbol can be interned in at most one package at a time.
-string, but not necessarily unique. A symbol name is unique within a package,
-however: two symbols cannot be in the same package if they have the same name.
-Moreover, a symbol cannot exist in more than one package at at time, although
-it can be relocated from one package to another. Symbols can exist which are
-not in packages: these are called uninterned symbols.
+Eacy symbol has a name, which is a string. It is not necessarily unique:
+two distinct symbols can have the sama name. However, a symbol name is unique
+within a package, because it serves as the key which associates the
+symbol with the package. Two symbols cannot be in the same package if they
+have the same name. Moreover, a symbol cannot exist in more than one package
+at at time, although it can be relocated from one package to another. A
+symbols exist which is not entered into any package: such a symbol is
+called "uninterned".
Packages are held in a global list which can be used to search for a package by
-name. The find-package function performs this lookup. A package may be
-deleted from the list with the delete-package function, but it continues
+name. The
+.code find-package
+function performs this lookup. A package may be
+deleted from the list with the
+.code delete-package
+function, but it continues
to exist until the program loses the last reference to that package.
-.SS Special variables *user-package*, *keyword-package*, *system-package*
-
-These variables hold predefined packages. The *user-package* is the one
+.coNP Special variables @, *user-package* @, *keyword-package* and @ *system-package*
+.desc
+These variables hold predefined packages. The
+.code *user-package*
+is the one
in which symbols are read when a TXR program is being scanned.
-The *keyword-package* holds keyword symbols, which are printed with
-a leading colon. The *system-package* is for internal symbols, helping
+The
+.code *keyword-package*
+holds keyword symbols, which are printed with
+a leading colon. The
+.code *system-package*
+is for internal symbols, helping
the implementation avoid name clashes with user code in some situations.
-.SS Function make-sym
-
-.TP
-Syntax:
-
- (make-sym <name>)
-
-Description:
-
-The make-sym function creates and returns a new symbol object. The argument
-<name>, which must be a string, specifies the name of the symbol. The symbol
+.coNP Function @ make-sym
+.synb
+.mets (make-sym << name )
+.syne
+.desc
+The
+.code make-sym
+function creates and returns a new symbol object. The argument
+.metn name ,
+which must be a string, specifies the name of the symbol. The symbol
does not belong to any package (it is said to be "uninterned").
-Note: an uninterned symbol can be interned into a package with the rehome-sym
-function. Also see the intern function.
-
-.SS Function gensym
-
-.TP
-Syntax:
-
- (gensym [<prefix>])
-
-Description
+Note: an uninterned symbol can be interned into a package with the
+.code rehome-sym
+function. Also see the
+.code intern
+function.
-The gensym function is similar to make-sym. It creates and returns a new
-symbol object. If the <prefix> argument is omitted, it defaults to "g".
+.coNP Function @ gensym
+.synb
+.mets (gensym <> [ prefix ])
+.syne
+.desc
+The
+.code gensym
+function is similar to make-sym. It creates and returns a new
+symbol object. If the
+.meta prefix
+argument is omitted, it defaults to
+.strn g .
Otherwise it must be a string.
-The difference between gensym and make-sym is that gensym creates the name
+The difference between
+.code gensym
+and
+.code make-sym
+is that
+.code gensym
+creates the name
by combining the prefix with a numeric suffix.
The numeric suffix is a decimal digit string, taken from the value of
-the variable *gensym-counter*, after incrementing it.
-
-Note: the variation in name is not the basis of the uniqueness of gensym; the
-basis of its uniqueness is that it is a freshly instantiated object. make-sym
-also returns unique symbols even if repeatedly called with the same string.
-
-.SS Special variable *gensym-counter*
+the variable
+.codn *gensym-counter* ,
+after incrementing it.
+
+Note: the variation in name is not the basis of the uniqueness assurance
+offered by
+.code make-sym
+and
+.codn gensym ;
+the basis is that the returned symbol is a freshly instantiated object.
+.code make-sym
+still returns unique symbols even if repeatedly called with the same
+string.
-This variable is initialized to 0. Each time the gensym function is called,
+.coNP Special variable @ *gensym-counter*
+.desc
+This variable is initialized to 0. Each time the
+.code gensym
+function is called,
it is incremented. The incremented value forms the basis of the numeric
suffix which gensym uses to form the name of the new symbol.
-.SS Function make-package
-
-.TP
-Syntax:
-
- (make-package <name>)
-
-.TP
-Description:
-
-The make-package function creates and returns a package named <name>, where
-<name> is a string. It is an error if a package by that name exists already.
-
-.SS Function packagep
-
-.TP
-Syntax:
-
- (packagep <obj>)
-
-.TP
-Description:
-
-The packagep function returns t if <obj> is a package, otherwise it returns
-nil.
-
-.SS Function find-package
-
-.TP
-Syntax:
-
- (find-package <name>)
-
-.TP
-Description:
-
-The argument <name> should be a string. If a package called <name> exists,
-then it is returned. Otherwise nil is returned.
-
-.SS Function intern
-
-.TP
-Syntax:
-
- (intern <name> [<package>])
-
-.TP
-Description:
-
-The argument <name> should be a symbol. The optional argument <package>
-should be a package. If <package> is not supplied, then the value
-taken is that of *user-package*.
+.coNP Function @ make-package
+.synb
+.mets (make-package << name )
+.syne
+.desc
+The
+.code make-package
+function creates and returns a package named
+.metn name ,
+where
+.meta name
+is a string. It is an error if a package by that name exists already.
+
+.coNP Function @ packagep
+.synb
+.mets (packagep << obj )
+.syne
+.desc
+The
+.code packagep
+function returns
+.codet
+if
+.meta obj
+is a package, otherwise it returns
+.codn nil .
+
+.coNP Function @ find-package
+.synb
+.mets (find-package << name )
+.syne
+.desc
+The argument
+.meta name
+should be a string. If a package called
+.meta name
+exists,
+then it is returned. Otherwise
+.code nil
+is returned.
-The intern function searches <package> for a symbol called <name>.
-If that symbol is found, it is returned. If that symbol is not found,
-then a new symbol called <name> is created and inserted into <package>,
+.coNP Function @ intern
+.synb
+.mets (intern < name <> [ package ])
+.syne
+.desc
+The argument
+.meta name
+should be a symbol. The optional argument
+.meta package
+should be a package. If
+.meta package
+is not supplied, then the value
+taken is that of
+.codn *user-package* .
+
+The
+.code intern
+function searches
+.meta package
+for a symbol called
+.metn name .
+If that symbol is found, it is returned. If that symbol is not found,
+then a new symbol called
+.meta name
+is created and inserted into
+.metn package ,
and that symbol is returned. In this case, the package becomes the
symbol's home package.
-.SS Function rehome-sym
-
-.TP
-Syntax:
-
- (rehome-sym <symbol> [<package>])
-
-.TP
-Description:
-
-The arguments <symbol> and <package> must be a symbol and package object,
-respectively. If <package> is not given, then it defaults to the value of
-*user-package*.
-
-The rehome-sym function moves <symbol> into <package>. If <symbol>
+.coNP Function @ rehome-sym
+.synb
+.mets (rehome-sym < symbol <> [ package ])
+.syne
+.desc
+The arguments
+.meta symbol
+and
+.meta package
+must be a symbol and package object,
+respectively. If
+.meta package
+is not given, then it defaults to the value of
+.codn *user-package* .
+
+The
+.code rehome-sym
+function moves
+.meta symbol
+into
+.metn package .
+If
+.meta symbol
is already in a package, it is first removed from that package.
-If a symbol of the same name exists in <package> that symbol is first removed
-from <package>.
-
-.SS Function symbolp
-
-.TP
-Syntax:
-
- (symbolp <obj>)
-
-.TP
-Description:
-
-The symbolp function returns t if <obj> is a symbol, otherwise it returns
-nil.
-
-.SS Function symbol-name
-
-.TP
-Syntax:
-
- (symbol-name <symbol>)
-
-.TP
-Description:
-
-The symbol-name function returns the name of <symbol>.
-
-.SS Function symbol-package
-
-.TP
-Syntax:
-
- (symbol-package <symbol>)
-
-.TP
-Description:
-
-The symbol-package function returns the home package of <symbol>.
-
-.SS Function packagep
-
-.TP
-Syntax:
-
- (packagep <obj>)
-
-.TP
-Description:
-
-The packagep function returns t if <obj> is a package, otherwise it returns
-nil.
-
-.SS Function keywordp
-
-.TP
-Syntax:
-
- (keywordp <obj>)
-
-.TP
-Description:
-
-The keywordp function returns t if <obj> is a keyword symbol, otherwise it
-returns nil.
-
-
-.SH PSEUDO-RANDOM NUMBERS
-
-.SS Special variable *random-state*
-
-The *random-state* variable holds an object which encapsulates the state
-of a pseudo-random number generator. This variable is the default argument for
-the random-fixnum and random functions, so that programs can be written
-which are not concerned about the management of random state.
-
-However, programs can create and manage random states, making it possible to
-obtain repeatable sequences of pseudo-random numbers which do not interfere
-with each other. For instance objects or modules in a program can have their
-own independent streams of random numbers which are repeatable, independently
-of other modules making calls to the random number functions.
-
-When TXR starts up, the *random-state* variable is initialized with
+If a symbol of the same name exists in
+.meta package
+that symbol is first removed
+from
+.metn package .
+
+.coNP Function @ symbolp
+.synb
+.mets (symbolp << obj )
+.syne
+.desc
+The
+.code symbolp
+function returns
+.code t
+if
+.meta obj
+is a symbol, otherwise it returns
+.codn nil .
+
+.coNP Function @ symbol-name
+.synb
+.mets (symbol-name << symbol )
+.syne
+.desc
+The
+.code symbol-name
+function returns the name of
+.metn symbol .
+
+.coNP Function @ symbol-package
+.synb
+.mets (symbol-package << symbol )
+.syne
+.desc
+The
+.code symbol-package
+function returns the home package of
+.metn symbol .
+
+.coNP Function @ packagep
+.synb
+.mets (packagep << obj )
+.syne
+.desc
+The
+.code packagep
+function returns
+.code t
+if
+.meta obj
+is a package, otherwise it returns
+.codn nil .
+
+.coNP Function @ keywordp
+.synb
+.mets (keywordp << obj )
+.syne
+.desc
+The
+.code keywordp
+function returns
+.code t
+if
+.meta obj
+is a keyword symbol, otherwise it
+returns
+.codn nil .
+
+.SS* Pseudo-random Numbers
+.coNP Special variable @ *random-state*
+.desc
+The
+.code *random-state*
+variable holds an object which encapsulates the state
+of a pseudo-random number generator. This variable is the default argument
+value for the
+.code random-fixnum
+and
+.codn random functions ,
+for the convenience of writing programs which are not concerned about the
+management of random state.
+
+On the other hand, programs can create and manage random states, making it
+possible to obtain repeatable sequences of pseudo-random numbers which do not
+interfere with each other. For instance objects or modules in a program can
+have their own independent streams of random numbers which are repeatable,
+independently of other modules making calls to the random number functions.
+
+When TXR starts up, the
+.code *random-state*
+variable is initialized with
a newly created random state object, which is produced as if by
-the call (make-random-state 42).
-
-.SS Function make-random-state
-
-.TP
-Syntax:
-
- (make-random-state [<seed>])
-
-.TP
-Description:
-
-The make-random-state function creates and returns a new random state,
-an object of the same kind as what is stored in the *random-state* variable.
+the call
+.codn (make-random-state 42) .
+
+.coNP Function @ make-random-state
+.synb
+.mets (make-random-state <> [ seed ])
+.syne
+.desc
+The
+.code make-random-state
+function creates and returns a new random state,
+an object of the same kind as what is stored in the
+.code *random-state*
+variable.
The seed, if specified, must be an integer value.
Note that the sign of the seed is ignored, so that negative seed
values are equivalent to their additive inverses.
-If the seed is not specified, then make-random-state produces a seed based
+If the seed is not specified, then
+.code make-random-state
+produces a seed based
on some information in the process environment, such as current
-time of day. It is not guaranteed that two calls to (make-random-state nil)
+time of day. It is not guaranteed that two calls to
+.code (make-random-state nil)
that are separated by less than some minimum increment of real time produce
-different seeds. The minimum time increment depends on the platform, but on any
-given platform, it is the platform's smallest available time increment, or a
-microsecond, whichever is longer.
-
-Of course, it is not guaranteed that any two calls to make-random-state produce
-different values under any circumstances, due to possible collisions; however,
-time differences smaller than the minimum increment may predictably produce
-identical values.
-
-For instance, on a platform with a nanosecond-resolution real-time clock,
-the minimum time increment is a microsecond. Calls to make-random-state
-closer together than a microsecond may predictably produce the same seed.
+different seeds. The minimum time increment depends on the platform.
-In a platform with a millisecond-resolution real-time clock, the minimum
+On a platform with a millisecond-resolution real-time clock, the minimum
time increment is a millisecond. Calls to make-random-state less than
a millisecond apart may predictably produce the same seed.
-.SS Function random-state-p
-
-.TP
-Syntax:
-
- (random-state-p <obj>)
-
-.TP
-Description:
-
-The random-state-p function returns t if <obj> is a random state, otherwise it
-returns nil.
-
-.SS Functions random-fixnum, random and rand
-
-.TP
-Syntax:
-
- (random-fixnum [<random-state>])
- (random <random-state> <modulus>)
- (rand <modulus> [<random-state>])
-
-.TP
-Description:
-
+.coNP Function @ random-state-p
+.synb
+.mets (random-state-p << obj )
+.syne
+.desc
+The
+.code random-state-p
+function returns
+.code t
+if
+.meta obj
+is a random state, otherwise it
+returns
+.codn nil .
+
+.coNP Functions @, random-fixnum @ random and @ rand
+.synb
+.mets (random-fixnum <> [ random-state ])
+.mets (random < random-state << modulus )
+.mets (rand < modulus <> [ random-state ])
+.syne
+.desc
All three functions produce pseudo-random numbers, which are positive integers.
The numbers are obtained from a WELLS 512 pseudo-random number generator, whose
state is stored in the random state object.
-The random-fixnum function produces a random fixnum integer: a reduced range
+The
+.code random-fixnum
+function produces a random fixnum integer: a reduced range
integer which fits into a value that does not have to be heap-allocated.
-The random and rand functions produce a value in the range [0, modulus). They
-differ only in the order of arguments. In the rand function, the random state
+The
+.code random
+and
+.code rand
+functions produce a value in the range [0,
+.metn modulus ).
+They differ only in the order of arguments. In the
+.code rand
+function, the random state
object is the second argument and is optional. If it is omitted, the global
-*random-state* object is used.
-
-.SH TIME
-
-.SS Functions time and time-usec
-
-.TP
-Syntax:
+.code *random-state*
+object is used.
+.SS* Time
+.coNP Functions @ time and @ time-usec
+.synb
(time)
(time-usec)
-
-.TP
-Description:
-
-The time function returns the number of seconds that have elapsed since
+.syne
+.desc
+The
+.code time
+function returns the number of seconds that have elapsed since
midnight, January 1, 1970, in the UTC timezone.
-The time-usec function returns a cons cell whose car field holds the seconds
-measured in the same way, and whose cdr field extends the precision by giving
+The
+.code time-usec
+function returns a cons cell whose
+.code car
+field holds the seconds measured in the same way, and whose
+.code cdr
+field extends the precision by giving
number of microseconds as an integer value between 0 and 999999.
-.SS Functions time-string-local and time-string-utc
-
-.TP
-Syntax:
-
- (time-string-local <time> <format>)
- (time-string-utc <time> <format>)
-
-.TP
-Description:
-
-These functions take the numeric time returned by the time function,
-and convert it to a textual representation in a very flexible way, according to
-a detailed format string.
-
-The time-string-local function converts the time to the local timezone of
-the host system. The time-string-utc function produces time in UTC.
-
-The <format> argument is a string, and follows exactly the same conventions as
-the format string of the C library function strftime.
-
-The <time> argument is an integer representing seconds obtained from the
-time function or from the time-usec function.
-
-.SS Functions time-fields-local and time-fields-utc
-
-.TP
-Syntax:
-
- (time-fields-local <time>)
- (time-fields-utc <time>)
+.coNP Functions @ time-string-local and @ time-string-utc
+.synb
+.mets (time-string-local < time << format )
+.mets (time-string-utc < time << format )
+.syne
+.desc
+These functions take the numeric time returned by the
+.code time
+function, and convert it to a textual representation in a flexible way,
+according to the contents of the
+.meta format
+string.
-.TP
-Description:
+The
+.code time-string-local
+function converts the time to the local timezone of
+the host system. The
+.code time-string-utc
+function produces time in UTC.
+
+The
+.meta format
+argument is a string, and follows exactly the same conventions as
+the format string of the C library function
+.codn strftime .
+
+The
+.meta time
+argument is an integer representing seconds obtained from the
+time function or from the
+.code car
+field of the cons returned by the
+.code time-usec
+function.
+.coNP Functions @ time-fields-local and @ time-fields-utc
+.synb
+.mets (time-fields-local << time )
+.mets (time-fields-utc << time )
+.syne
+.desc
These functions take the numeric time returned by the time function,
and convert it to a list of seven fields.
-The time-string-local function converts the time to the local timezone of
-the host system. The time-string-utc function produces time in UTC.
+The
+.code time-string-local
+function converts the time to the local timezone of
+the host system. The
+.code time-string-utc
+function produces time in UTC.
-The fields returned as a list are six integers, and a boolean value.
+The fields returned as a list consist of six integers, and a boolean value.
The six integers represent the year, month, day, hour, minute and second.
The boolean value indicates whether daylight savings time is in effect
-(always nil in the case of time-fields-utc).
-
-The <time> argument is an integer representing seconds obtained from the
-time function or from the time-usec function.
-
-.SS Functions make-time and make-time-utc
-
-.TP
-Syntax:
-
- (make-time <year> <month> <day> <hour> <minute> <second> <dst-advice>)
- (make-time-utc <year> <month> <day> <hour> <minute> <second> <dst-advice>)
-
-.TP
-Description
+(always
+.code nil
+in the case of
+.codn time-fields-utc ).
+
+The
+.meta time
+argument is an integer representing seconds obtained from the
+.code time
+function or from the
+.code time-usec
+function.
-The make-time function returns a time value, similar to the one returned by the
-time function. The time value is constructed not from the system clock, but
-from a date and time specified as arguments. The <year> argument is a
-calendar year, like 2013. The <month> argument ranges from 1 through 12.
+.coNP Functions @ make-time and @ make-time-utc
+.synb
+.mets (make-time < year < month < day < hour < minute < second << dst-advice )
+.mets (make-time-utc < year < month < day < hour < minute < second << dst-advice )
+.syne
+.desc
+The
+.code make-time
+function returns a time value, similar to the one returned by the
+.code time
+function. The
+.code time
+value is constructed not from the system clock, but
+from a date and time specified as arguments. The
+.meta year
+argument is a calendar year, like 2014.
+The
+.meta month
+argument ranges from 1 to 12.
+The
+.meta hour
+argument is a 24-hour time, ranging from 0 to 23.
These arguments represent a local time, in the current time zone.
-The <dst-advice> argument specifies whether the time is expressed in
-daylight savings time (DST). It takes on these values: nil, the keyword :auto,
-or any other value which denotes boolean true.
+The
+.meta dst-advice
+argument specifies whether the time is expressed in
+daylight savings time (DST). It takes on three possible values:
+.codn nil ,
+the keyword
+.codn :auto ,
+or else the symbol
+.codn t .
+Any other value has the same interpretation as
+.codn t .
-If <dst-advice> is t, then the time is assumed to be expressed in DST.
-If the argument is nil, then the time is assumed not to be in DST.
-If <dst-advice> is :auto, then the function tries to determine whether
+If
+.meta dst-advice
+is
+.codn t ,
+then the time is assumed to be expressed in DST.
+If the argument is
+.codn nil ,
+then the time is assumed not to be in DST.
+If
+.meta dst-advice
+is
+.codn :auto ,
+then the function tries to determine whether
DST is in effect in the current time zone for the specified date and time.
-The make-time-utc function is similar to make-time, except that
-it treats the time as UTC rather than in the local time zone.
-The <dst-advice> argument is supported by make-time-utc for function
-call compatibility with make-time. It may or may not have any effect
+The
+.code make-time-utc
+function is similar to
+.codn make-time ,
+except that
+it treats the time as UTC rather than in the local time zone.
+The
+.meta dst-advice
+argument is supported by
+.code make-time-utc
+for function
+call compatibility with
+.codn make-time .
+It may or may not have any effect
on the output (since the UTC zone by definition doesn't have daylight
savings time).
-.SH ENVIRONMENT VARIABLES AND COMMAND LINE
-
-.SS Special variables *args* and *args-full*
-
-The *args* variable holds a list of strings representing the remaining
-arguments which follow any options processed by the txr executable, and the
-script name.
-
-The *args-full* variable holds the original, complete list of arguments passed
+.SS* Environment Variables and Command Line
+.coNP Special variables @ *args* and @ *args-full*
+.desc
+The
+.code *args*
+variable holds a list of strings representing the remaining
+arguments which follow any options processed by the
+.code txr
+executable, and the script name.
+
+The
+.code *args-full*
+variable holds the original, complete list of arguments passed
from the operating system.
-Note: the *args* variable is nil during the processing of the command line,
-so TXR Lisp invoked using the -p or -e option cannot use it.
-
-.SS Function env
-
-.TP
-Syntax:
-
+Note: the
+.code *args*
+variable is
+.code nil
+during the processing of the command line,
+so TXR Lisp expressions invoked using the
+.code -p
+or
+.code -e
+option cannot use it.
+
+.coNP Function @ env
+.synb
(env)
-
-.TP
-Description:
-
-The env function retrieves the list of environment variables. Each
+.syne
+.desc
+The
+.code env
+function retrieves the list of environment variables. Each
variable is represented by a single entry in the list: a string which
-contains an = (equal) character somewhere, separating the variable name
+contains an
+.code =
+(equal) character somewhere, separating the variable name
from its value.
-See also: the env-hash function.
-
-.SS Function env-hash
-
-Syntax:
+See also: the
+.code env-hash
+function.
+.coNP Function @ env-hash
+.synb
(env-hash)
-
-.TP
-Description:
-
-The env-hash function constructs and returns an :equal-based hash. The hash is
+.syne
+.desc
+The
+.code env-hash
+function constructs and returns an
+.code :equal-based
+hash. The hash is
populated with the environment variables, represented as key-value pairs.
-.SH UNIX PROGRAMMING
-
-.SS Function errno
-
-.TP
-Syntax:
-
- (errno [<new-errno>])
-
-.TP
-Description:
-
-These functions retrieves the current value of the C library error variable
-errno. If the argument <new-errno> is present and is not nil, then it
-specifies a value which is stored into errno. The value returned is the prior
-value.
-
-.SS Function exit
-
-.TP
-Syntax:
-
- (exit <status>)
-
-.TP
-Description:
-
-The exit function terminates the entire process (running TXR image), specifying
-the termination status to the operating system. Values of <status> may be nil,
-t, or integer values. The value nil corresponds to the C constant
-EXIT_FAILURE, and t corresponds to EXIT_SUCCESS. These are platform-independent
+.SS* Unix Programming
+.coNP Function @ errno
+.synb
+.mets (errno <> [ new-errno ])
+.syne
+.desc
+The
+.code errno
+function retrieves the current value of the C library error variable
+.codn errno .
+If the argument
+.meta new-errno
+is present and is not
+.codn nil ,
+then it
+specifies a value which is stored into
+.codn errno .
+The value returned is the prior value.
+
+.coNP Function @ exit
+.synb
+.mets (exit << status )
+.syne
+.desc
+The
+.code exit
+function terminates the entire process (running TXR image), specifying
+the termination status to the operating system. Values of
+.meta status
+may be
+.codn nil ,
+.codn t ,
+or an integer value. The value
+.code nil
+corresponds to the C constant
+.codn EXIT_FAILURE ,
+and
+.code t
+corresponds to
+.codn EXIT_SUCCESS .
+These are platform-independent
indicators of failed or successful termination. The numeric value 0 also
indicates success.
-.SS Function usleep
-
-.TP
-Syntax:
-
- (usleep <usec>)
-
-.TP
-Description:
-
-The usleep function suspends the execution of the program for at least
-<usec> microseconds.
-
-The return value is t if the sleep was successfully executed. A nil
+.coNP Function @ usleep
+.synb
+.mets (usleep << usec )
+.syne
+.desc
+The
+.code usleep
+function suspends the execution of the program for at least
+.meta usec
+microseconds.
+
+The return value is
+.code t
+if the sleep was successfully executed. A
+.code nil
value indicates premature wakeup or complete failure.
Note: the actual sleep resolution is not guaranteed, and depends on granularity
@@ -14428,181 +22322,230 @@ of the system timer. Actual sleep times may be rounded up to the nearest 10
millisecond multiple on a system where timed suspensions are triggered by a 100
Hz tick.
-.SS Function mkdir
-
-.TP
-Syntax:
-
- (mkdir <path> [<mode>])
-
-.TP
-Description:
-
-Try to create the directory named <path> using the POSIX mkdir function.
-An exception of type file-error is thrown if the function fails. Returns
-t on success.
-
-The <mode> argument specifies the request numeric permissions
+.coNP Function @ mkdir
+.synb
+.mets (mkdir < path <> [ mode ])
+.syne
+.desc
+.code mkdir
+tries to create the directory named
+.meta path
+using the POSIX
+.code mkdir
+function.
+An exception of type
+.code file-error
+is thrown if the function fails. Returns
+.code t
+on success.
+
+The
+.meta mode
+argument specifies the request numeric permissions
for the newly created directory. If omitted, the requested permissions are
-#o777 (511): readable and writable to everyone. The requested permissions
-are subject to umask.
-
-.SS Function chdir
-
-.TP
-Syntax:
-
- (chdir <path>)
-
-.TP
-Description:
-
-This changes the current working directory to <path>, and returns t,
-or else throws an exception of type file-error.
-
-.SS Function pwd
-
-.TP
-Syntax:
-
+.code #o777
+(511): readable and writable to everyone. The requested permissions
+are subject to the system
+.codn umask .
+
+.coNP Function @ chdir
+.synb
+.mets (chdir << path )
+.syne
+.desc
+.code chdir
+changes the current working directory to
+.metn path ,
+and returns
+.metn t ,
+or else throws an exception of type
+.codn file-error .
+
+.coNP Function @ pwd
+.synb
(pwd)
-
-.TP
-Description:
-
-This function retrieves the current working directory.
-If the underlying getcwd system call fails with an errno other than ERANGE,
+.syne
+.desc
+The
+.code pwd
+function retrieves the current working directory.
+If the underlying
+.code getcwd
+C library function fails with an
+.code errno
+other than
+.codn ERANGE ,
an exception will be thrown.
-.SS Functions getpid and getppid
-
-.TP
-Syntax:
-
+.coNP Functions @ getpid and @ getppid
+.synb
(getpid)
(getppid)
-
-.TP
-Description:
-
+.syne
+.desc
These functions retrieve the current proces ID and the parent process ID
-respectively. They are wrappers for the POSIX functions getpid and getppid.
-
-.SS Function daemon
-
-.TP
-Syntax:
-
- (daemon <nochdir-p> <noclose-p>)
-
-.TP
-Description:
-
-This is a wrapper for the Unix function daemon of BSD origin.
-
-It returns t if successful, nil otherwise, and the errno
+respectively. They are wrappers for the POSIX functions
+.code getpid
+and
+.codn getppid .
+
+.coNP Function @ daemon
+.synb
+.mets (daemon < nochdir-p << noclose-p )
+.syne
+.desc
+This is a wrapper for the function
+.code daemon
+which originated in BSD Unix.
+
+It returns
+.code t
+if successful,
+.code nil
+otherwise, and the
+.code errno
variable is set in that case.
-.SS Functions makedev, minor, major
-
-.TP
-Syntax:
-
- (makedev <minor> <major>)
- (minor <dev>)
- (major <dev>)
-
-.TP
-Description:
-
-The parameters <minor>, <major> and <dev> are all integers. The makedev
+.coNP Functions @, makedev @ minor and @ major
+.synb
+.mets (makedev < minor << major )
+.mets (minor << dev )
+.mets (major << dev )
+.syne
+.desc
+The parameters
+.metn minor ,
+.meta major
+and
+.meta dev
+are all integers. The
+.code makedev
function constructs a combined device number from a minor and major pair (by
-calling the Unix makedev function). This device number is suitable as an
-argument to the mknod function (see below). Device numbers also appear as :dev
-property returned by the stat function.
+calling the Unix
+.code makedev
+function). This device number is suitable as an
+argument to the
+.codee mknod
+function (see below). Device numbers also appear the
+.code :dev
+property returned by the
+.code stat
+function.
-The minor and major functions extract the minor and major device number
+The
+.code minor
+and
+.code major
+functions extract the minor and major device number
from a combined device number.
-.SS Function mknod
-
-.TP
-Syntax:
-
- (mknod <path> <mode> [<dev>])
-
-.TP
-Description:
-
-The mknod function tries to create an entry in the filesystem: a file,
-FIFO, or a device special file, under the name <path>. If it is successful,
-it returns t, otherwise it throws an exception of type file-error.
-
-The <mode> argument is a bitwise "or" combination of the requested permissions,
-and the type of object to create: one of the constants s-ifreg, s-ififo,
-s-ifchr or s-ifblk or s-ifsock. The permissions are subject to the umask.
-
-If a block or character special device (s-ifchr or s-ifblk) is being
-created, then the <dev> argument specifies the major and minor numbers
+.coNP Function @ mknod
+.synb
+.mets (mknod < path < mode <> [ dev ])
+.syne
+.desc
+The
+.code mknod
+function tries to create an entry in the filesystem: a file,
+FIFO, or a device special file, under the name
+.metn path .
+If it is successful,
+it returns
+.codn t ,
+otherwise it throws an exception of type
+.codn file-error .
+
+The
+.meta mode
+argument is a bitwise or combination of the requested permissions,
+and the type of object to create: one of the constants
+.codn s-ifreg ,
+.codn s-ififo ,
+.codn s-ifchr ,
+.code s-ifblk
+or
+.codn s-ifsock .
+The permissions are subject to the system
+.codn umask .
+
+If a block or character special device
+.cod2 ( s-ifchr
+or
+.codn s-ifblk )
+is being
+created, then the
+.meta dev
+argument specifies the major and minor numbers
of the device. A suitable value can be constructed from a major and minor
-pair using the makedev function.
+pair using the
+.code makedev
+function.
-.TP
-Example:
+.TP* Example:
+.cblk
;; make a character device (8, 3) called /dev/foo
;; requesting rwx------ permissions
(mknod "dev/foo" (logior #o700 s-ifchr) (makedev 8 3))
-
-.SS Functions symlink and link
-
-.TP
-Syntax:
-
- (symlink <target> <path>)
- (link <target> <path>)
-
-.TP
-Description:
-
-The symlink function creates a symbolic link called <path> whose contents
-are the absolute or relative path <target>. <target> does not actually have
-to exist.
-
-The link function creates a hard link. The object at <target> is installed
-into the filesystem at <path> also.
-
-If these functions succeed, they return t. Otherwise they throw an exception
-of type file-error.
-
-.SS Function readlink
-
-.TP
-Syntax:
-
- (readlink <path>)
-
-.TP
-Description:
-
-If <path> names a filesystem object which is a symbolic link, the readlink
+.cble
+
+.coNP Functions @ symlink and @ link
+.synb
+.mets (symlink < target << path )
+.mets (link < target << path )
+.syne
+.desc
+The
+.code symlink
+function creates a symbolic link called
+.meta path
+whose contents
+are the absolute or relative path
+.metn target .
+.meta target
+does not actually have to exist.
+
+The link function creates a hard link. The object at
+.meta target
+is installed
+into the filesystem at
+.meta path
+also.
+
+If these functions succeed, they return
+.codn t .
+Otherwise they throw an exception
+of type
+.codn file-error .
+
+.coNP Function @ readlink
+.synb
+.mets (readlink << path )
+.syne
+.desc
+If
+.meta path
+names a filesystem object which is a symbolic link, the
+.code readlink
function reads the contents of that symbolic link and returns it
-as a string. Otherwise, it fails by throwing an exception of type file-error.
-
-.SS Functions sh and run
-
-.TP
-Syntax:
-
- (sh <system-command>)
- (run <program> [<argument-list>])
-
-.TP
-Description:
-
-The sh function executes <system-command> using the system command interpreter.
-The run function spawns a <program>, searching for it using the
+as a string. Otherwise, it fails by throwing an exception of type
+.codn file-error .
+
+.coNP Functions @ sh and @ run
+.synb
+.mets (sh << system-command )
+.mets (run < program <> [ argument-list ])
+.syne
+.desc
+The
+.code sh
+function executes
+.meta system-command
+using the system command interpreter.
+The run function spawns a
+.metn program ,
+searching for it using the
system PATH. Using either method, the executed process receives environment
variables from the parent.
@@ -14610,105 +22553,166 @@ TXR blocks until the process finishes executing. If the program terminates
normally, then its integer exit status is returned. The value zero indicates
successful termination.
-The return value nil indicates an abnormal termination, or the inability
+The return value
+.code nil
+indicates an abnormal termination, or the inability
to run the process at all.
-In the case of the run function, if the child process is created successfully
-but the program cannot be executed, then the exit status will be an errno value
-from the failed exec attempt.
+In the case of the
+.code run
+function, if the child process is created successfully
+but the program cannot be executed, then the exit status will be an
+.code errno
+value from the failed
+.code exec
+attempt.
-.SH UNIX SIGNAL HANDLING
+.SS* Unix Signal Handling
On platforms where certain advanced features of POSIX signal handling are
available at the C API level, TXR exposes signal-handling functionality.
-A TXR program can install a TXR Lisp function (such as an anonymous lambda,
+A TXR program can install a TXR Lisp function (such as an anonymous.
+codn lambda ,
or the function object associated with a named function) as the handler for
a signal.
When that signal is delivered, TXR will intercept it with its own safe,
internal handler, mark the signal as deferred (in a TXR sense) and then
-dispatch the lambda at a convenient time.
+dispatch the registered function at a convenient time.
Handlers currently are not permitted to interrupt the execution of most TXR
internal code. Immediate, asynchronous execution of handlers is currently
-enabled only while TXR is blocked on I/O operations or sleep on a tail stream.
-Additionally, the sig-check function can be used to dispatch and clear deferred
+enabled only while TXR is blocked on I/O operations or sleeping.
+Additionally, the
+.code sig-check
+function can be used to dispatch and clear deferred
signals. These handlers are then safely called if they were subroutines of
-sig-check, and not asynchronous interrupts.
-
-.SS Special variables sig-hup, sig-int, sig-quit, sig-ill, sig-trap, sig-abrt, sig-bus, sig-fpe, sig-kill, sig-usr1, sig-segv, sig-usr2, sig-pipe, sig-alrm, sig-term, sig-chld, sig-cont, sig-stop, sig-tstp, sig-ttin, sig-ttou, sig-urg, sig-xcpu, sig-xfsz, sig-vtalrm, sig-prof, sig-poll, sig-sys, sig-winch, sig-iot, sig-stkflt, sig-io, sig-lost and sig-pwr
-
-.TP
-Description:
-
-These variables correspond to the C signal constants SIGHUP, SIGINT and so forth.
-The variables sig-winch, sig-iot, sig-stkflt, sig-io, sig-lost and sig-pwr may not be
-available since a system may lack the corresponding signal constants. See notes
-for the log log-authpriv below. The remaining signal constants are described in
-the Single Unix Specification and are expected by TXR to be present.
+.codn sig-check ,
+and not asynchronous interrupts.
+
+.coNP Special variables @, sig-hup @, sig-int @, sig-quit @, sig-ill @, sig-trap @, sig-abrt @, sig-bus @, sig-fpe @, sig-kill @, sig-usr1 @, sig-segv @, sig-usr2 @, sig-pipe @, sig-alrm @, sig-term @, sig-chld @, sig-cont @, sig-stop @, sig-tstp @, sig-ttin @, sig-ttou @, sig-urg @, sig-xcpu @, sig-xfsz @, sig-vtalrm @, sig-prof @, sig-poll @, sig-sys @, sig-winch @, sig-iot @, sig-stkflt @, sig-io @ sig-lost and @ sig-pwr
+.desc
+These variables correspond to the C signal constants
+.codn SIGHUP ,
+.code SIGINT
+and so forth.
+The variables
+.codn sig-winch ,
+.codn sig-iot ,
+.codn sig-stk flt,
+.codn sig-io ,
+.code sig-lost
+and
+.code sig-pwr
+may not be available since a system may lack the corresponding signal
+constants. See notes for the function
+.codn log-authpriv .
The highest signal number is 31.
-
-.SS Functions set-sig-handler and get-sig-handler
-
-.TP
-Syntax:
-
- (set-sig-handler <signal-number> <handling-spec>)
- (get-sig-handler <signal-number>)
-
-.TP
-Description:
-
-The set-sig-handler function is used to specify the handling for a signal, such
+.coNP Functions @ set-sig-handler and @ get-sig-handler
+.synb
+.mets (set-sig-handler < signal-number << handling-spec )
+.mets (get-sig-handler << signal-number )
+.syne
+.desc
+The
+.code set-sig-handler
+function is used to specify the handling for a signal, such
as the installation of a handler function. It updates the signal handling for
-a signal whose number is <signal-number> (usually one of the constants like
-sig-hup, sig-int and so forth), and returns the previous value. The
-get-sig-handler function returns the current value.
-
-The <signal-number> must be an integer the range 1 to 31.
-
-Initially, all 31 signal handling specifications are set to the value t.
-
-The <handling-spec> parameter may be a function. If a function is specified,
+a signal whose number is
+.meta signal-number
+(usually one of the constants like
+.codn sig-hup ,
+.code sig-int
+and so forth), and returns the previous value. The
+.code get-sig-handler
+function returns the current value.
+
+The
+.meta signal-number
+must be an integer the range 1 to 31.
+
+Initially, all 31 signal handling specifications are set to the value
+.codn t .
+
+The
+.meta handling-spec
+parameter may be a function. If a function is specified,
then the signal is enabled and connected to that function until another
-call to set-sig-handler changes the handling for that signal.
+call to
+.code set-sig-handler
+changes the handling for that signal.
-If <handling-spec> is the symbol nil, then the function previously associated
+If
+.meta handling-spec
+is the symbol
+.codn nil ,
+then the function previously associated
with the signal, if any, is removed, and the signal is disabled. For a signal
-to be disabled means that the signal is set to the SIG_IGN disposition (refer to
-the C API).
+to be disabled means that the signal is set to the
+.code SIG_IGN
+disposition (refer to the C API).
-If <handling-spec> is the symbol t, then the function previously associated
+If
+.meta handling-spec
+is the symbol
+.codn t ,
+then the function previously associated
with the signal, if any, is removed, and the signal is set to its default
-disposition. This means that it is set to SIG_DFL (refer to the C API).
-Some signals terminate the process in their default disposition.
-
-Note that the certain signals like sig-quit and sig-kill cannot be handled.
+disposition. This means that it is set to
+.code SIG_DFL
+(refer to the C API).
+Some signals terminate the process if they are generated while the
+handling is configured to the default disposition.
+
+Note that the certain signals like
+.code sig-quit
+and
+.code sig-kill
+cannot be ignored or handled.
Please observe the signal documentation in the IEEE POSIX standard, and your
platform.
A signal handling function must take two arguments. It is of the form:
- (lambda (signal async-p) ...)
-
-The signal argument is an integer indicating the signal number for which the
-handler is being invoked. The asyncp-p argument is a boolean value, nil or t.
-If it is t, it indicates that the handler is being invoked
-asynchronously - directly in a signal handling context. If it is nil, then it
+.cblk
+.mets (lambda >> ( signal << async-p ) ...)
+.cble
+
+The
+.meta signal
+argument is an integer indicating the signal number for which the
+handler is being invoked. The
+.meta asyncp-p
+argument is a boolean value.
+If it is
+.codn t ,
+it indicates that the handler is being invoked
+asynchronously\(emdirectly in a signal handling context. If it is
+.codn nil ,
+then it
is a deferred call. Handlers may do more things in a deferred call, such
as terminate by throwing exceptions, and perform I/O.
The return value of a handler is normally ignored. However if it invoked
-asynchronously (the async-p argument is true), then if the handler returns
-a true value (any value other than nil), the handler is understood as
+asynchronously (the
+.meta async-p
+argument is true), then if the handler returns
+a
+.cod2 non- nil
+value, it is understood that the handler
requesting that it be deferred. This means that the signal will be marked
-as deferred, and handler will be called one more time again at some later
-time in a deferred context (async-p nil). This is not guaranteed, however;
+as deferred, and the handler will be called again at some later
+time in a deferred context, whereby
+.meta async-p
+is
+.codn nil .
+This is not guaranteed, however;
it's possible that another signal will arrive before that happens,
-possibly resulting in an async call.
+possibly resulting in another async call, so the handler must
+be prepared to deal with an async call at any time.
If a handler is invoked synchronously, then its return value is ignored.
@@ -14716,227 +22720,313 @@ In the current implementation, signals do not queue. If a signal is delivered
to the process again, while it is marked as deferred, it simply stays deferred;
there is no counter associated with a signal, only a boolean flag.
-.SS The sig-check function
-
-.TP
-Syntax:
-
+.coNP The @ sig-check function
+.synb
(sig-check)
-
-.TP
-Description:
-
-The sig-check function tests whether any signals are deferred, and for each
+.syne
+.desc
+The
+.code sig-check
+function tests whether any signals are deferred, and for each
deferred signal in turn, it executes the corresponding handler. For a signal to
be deferred means that the signal was caught by an internal handler in TXR and
the event was recorded by a flag. If a handler function is removed while a
signal is deferred, the deferred flag is cleared for that signal.
-Calls to the sig-check function may be inserted into CPU-intensive code that
+Calls to the
+.code sig-check
+function may be inserted into CPU-intensive code that
has no opportunity to be interrupted by signals, because it doesn't invoke any
I/O functions.
-.SS The kill function
-
-.TP
-Syntax:
-
- (kill <process-id> [<signal>])
-
-.TP
-Description:
-
-The kill function is used for sending a signal to a process group or process.
-It is a wrapper for the POSIX kill function.
-
-If the <signal> argument is omitted, it defaults to the same value as sig-term.
-
-.SH UNIX ITIMERS
-
-Itimers can be used in combination with signal handling to execute asynchronous
-actions. Itimers deliver one-time or periodic signals. For more information,
-consult the POSIX specification.
-
-.SS Variables itimer-real, itimer-virtual and itimer-prof
-
-.TP
-Description:
-
-These variables correspond to the POSIX constants ITIMER_REAL, ITIMER_VIRTUAL
-and ITIMER_PROF. Thir values are suitable as the <timer> argument of
-the getitimer and setitimer functions.
-
-.SS Functions getitimer and setitimer
-
-.TP
-Syntax:
-
- (getitimer <timer>)
- (setitimer <timer> <interval> <value>)
-
-.TP
-Description
+.coNP The @ kill function
+.synb
+.mets (kill < process-id <> [ signal ])
+.syne
+.desc
+The
+.code kill
+function is used for sending a signal to a process group or process.
+It is a wrapper for the POSIX
+.code kill
+function.
-The getitimer function returns the current value of the specified timer,
-which must be itimer-real, itimer-virtual or itimer-prof.
+If the
+.meta signal
+argument is omitted, it defaults to the same value as
+.codn sig-term .
+
+.SS* Unix Itimers
+Itimers ("interval timers") can be used in combination with signal handling to
+execute asynchronous actions. Itimers deliver delayed, one-time signals,
+and also periodically recurring signals. For more information, consult the
+POSIX specification.
+
+.coNP Variables @, itimer-real @, itimer-virtual and @ itimer-prof
+.desc
+These variables correspond to the POSIX constants
+.codn ITIMER_REAL ,
+.code ITIMER_VIRTUAL
+and
+.codn ITIMER_PROF .
+Their values are suitable as the
+.meta timer
+argument of the
+.code getitimer
+and
+.code setitimer
+functions.
+
+.coNP Functions @ getitimer and @ setitimer
+.synb
+.mets (getitimer << timer )
+.mets (setitimer < timer < interval << value )
+.syne
+.desc
+The
+.code getitimer
+function returns the current value of the specified timer,
+which must be
+.codn itimer-real ,
+.code itimer-virtual
+or
+.codn itimer-prof .
The current value consists of a list of two integer values, which
represents microseconds. The first value is the timer interval,
and the second value is the timer's current value.
-The setitimer function also retrieves the specified timer, exactly
-as getitimer. In addition, it stores a new value in the timer,
+Like
+.codn getitimer ,
+the
+.code setitimer
+function also retrieves the specified timer.
+In addition, it stores a new value in the timer,
which is given by the two arguments, expressed in microseconds.
-.SH UNIX SYSLOG
+.SS* Unix Syslog
On platforms where a Unix-like syslog API is available, TXR exports this
-interface. TXR programs can configure logging via the openlog function,
-control the logging mask via setlogmask and generate logs via syslog,
+interface. TXR programs can configure logging via the
+.code openlog
+function,
+control the logging mask via
+.code setlogmask
+and generate logs via
+.codn syslog ,
or using special syslog streams.
-.SS Special variables log-pid, log-cons, log-ndelay, log-odelay, log-nowait and log-perror
-
+.coNP Special variables @, log-pid @, log-cons @, log-ndelay @, log-odelay @ log-nowait and @ log-perror
+.desc
These variables take on the values of the corresponding C preprocessor
-constants from the <syslog.h> header: LOG_PID, LOG_CONS, etc. These
-integer values represent logging options used in the option argument to the
-openlog function.
-
-Note: LOG_PERROR is not in POSIX, and so log-perror might not be available.
-See notes about LOG_AUTHPRIV in the next section.
-
-.SS Special variables log-user, log-daemon, log-auth and log-authpriv
+constants from the
+.code <syslog.h>
+header:
+.codn LOG_PID ,
+.codn LOG_CON S, etc.
+These integer values represent logging options used in the option argument to
+the
+.code openlog
+function.
+Note:
+.code LOG_PERROR
+is not in POSIX, and so
+.code log-perror
+might not be available.
+See notes about
+.code LOG_AUTHPRIV
+in the documentation for
+.codn log-authpriv .
+
+.coNP Special variables @, log-user @, log-daemon @ log-auth and @ log-authpriv
+.desc
These variables take on the values of the corresponding C preprocessor
-constants from the <syslog.h> header: LOG_USER, LOG_DAEMON, LOG_AUTH
-and LOG_AUTHPRIV. These are the integer facility codes specified in the
-openlog function.
-
-Note: LOG_AUTHPRIV is not in POSIX, and so log-authpriv might not be available.
-For portability use code like (of (symbol-value 'log-authpriv) 0) to
-evaluate to 0 if log-authpriv doesn't exist, or else check for its
-existence using (boundp 'log-authpriv).
+constants from the
+.code <syslog.h>
+header:
+.codn LOG_USER ,
+.codn LOG_DAEMON ,
+.code LOG_AUTH
+and
+.codn LOG_AUTHPRIV .
+These are the integer facility codes specified in the
+.code openlog
+function.
-.SS Special variables log-emerg, log-alert, log-crit, log-err, log-warning, log-notice, log-info and log-debug
+Note:
+.code LOG_AUTHPRIV
+is not in POSIX, and so
+.code log-authpriv
+might not be available.
+For portability use code like
+.code (or (symbol-value 'log-authpriv) 0)
+to evaluate to 0 if
+.code log-authpriv
+doesn't exist, or else check for its existence
+using
+.codn (boundp 'log-authpriv) .
+
+.coNP Special variables @, log-emerg @, log-alert @, log-crit @, log-err @, log-warning @, log-notice @ log-info and @ log-debug
These variables take on the values of the corresponding C preprocessor
-constants from the <syslog.h> header: LOG_EMERG, LOG_ALERT, etc.
-These are the integer priority codes specified in the syslog call.
+constants from the
+.code <syslog.h>
+header:
+.codn LOG_EMERG ,
+.codn LOG_ALERT ,
+etc.
+These are the integer priority codes specified in the
+.code syslog
+function.
-.SS The *stdlog* special variable holds a special kind of stream: a syslog
-stream. Each newline-terminated line of text sent to this stream becomes a log
-message.
+.coNP The @ *stdlog* special variable
+.desc
+The
+.code *stdlog*
+variable holds a special kind of stream: a syslog stream. Each
+newline-terminated line of text sent to this stream becomes a log message.
The stream internally maintains a priority value that is applied
-when it generates messages. By default, this value is that of log-info.
-The stream holds the priority as the value of the :prio property,
-which may be changed with the stream-set-prop function.
+when it generates messages. By default, this value is that of
+.codn log-info .
+The stream holds the priority as the value of the
+.code :prio
+stream property, which may be changed with the
+.code stream-set-prop
+function.
The latest priority value which has been configured on the stream is used
at the time the newline character is processed and the log message
is generated, not necessarily the value which was in effect at the time the
accumulation of a line began to take place.
-Note that messages generated via the openlog function are not newline
-terminated; this is a convention of the syslog stream. The newline characters
-written to the syslog stream are only used to recognize the message framing,
-and are not sent to syslog.
-
-Multiple lines can be written to the stream in a single operation, and
-these result in multiple syslog messages.
-
-.SS The openlog function
-
-.TP
-Syntax:
-
- (openlog <id-string> [ <options> [<facility>] ])
-
-.TP
-Description:
-
-The openlog TXR Lisp function is a wrapper for the openlog C function, and the
-arguments have the same semantics. It is not necessary to use openlog in order
-to call the syslog function or to write data to *stdlog*. The call is necessary
-in order to override the default identifying string, to set options, such
-as having the PID (process ID) recorded in log messages, and to specify the facility.
-
-The <id-string> argument is mandatory.
-
-The <options> argument is a bitwise mask (see the logior function) of option
-values such as log-pid and log-cons. If it is missing, then a value of 0 is
+Messages sent to
+.code *stdlog*
+are delimited by newline characters. That is to say, each line of
+text written to the stream is a new log.
+
+.coNP The @ openlog function
+.synb
+.mets (openlog < id-string >> [ options <> [ facility ]])
+.syne
+.desc
+The
+.code openlog
+function is a wrapper for the
+.code openlog
+C function, and the
+arguments have the same semantics. It is not necessary to use
+.code openlog
+in order
+to call the
+.code syslog
+function or to write data to
+.codn *stdlog* .
+The call is necessary in order to override the default identifying string, to
+set options, such as having the PID (process ID) recorded in log messages, and
+to specify the facility.
+
+The
+.meta id-string
+argument is mandatory.
+
+The
+.meta option
+argument is a bitwise mask (see the logior function) of option
+values such as
+.code log-pid
+and
+.codn log-cons .
+If it is missing, then a value of 0 is
used, specifying the absence of any options.
-The <facility> argument is one of the values log-user, log-daemon or log-auth.
-If it is missing, then log-user is assumed.
-
-.SS The closelog function
-
-.TP
-Syntax:
-
+The
+.meta facility
+argument is one of the values
+.codn log-user ,
+.code log-daemon
+or
+.codn log-auth .
+If it is missing, then
+.code log-user
+is assumed.
+
+.coNP The @ closelog function
+.synb
(closelog)
-
-.TP
-Description:
-
-The closelog function is a wrapper for the C function closelog.
-
-.SS The setlogmask function
-
-.TP
-Syntax:
-
- (setlogmask <bitmask-integer>)
-
-.TP
-Description:
-
-The setlogmask function interfaces to the corresponding C function, and has the
-same argument and return value semantics. The argument is a mask of priority
+.syne
+.desc
+The
+.code closelog
+function is a wrapper for the C function
+.codn closelog .
+
+.coNP The @ setlogmask function
+.synb
+.mets (setlogmask << bitmask-integer )
+.syne
+.desc
+The
+.code setlogmask
+function interfaces to the corresponding C function, and has the
+same argument and return value semantics. The
+.meta bitmask-integer
+argument is a mask of priority
values to enable. The return value is the prior value. Note that if the
argument is zero, then the function doesn't set the mask to zero; it only
returns the current value of the mask.
-Note that the priority values like log-emerg and log-debug are integer
+Note that the priority values like
+.code log-emerg
+and
+.code log-debug
+are integer
enumerations, not bitmasks. These values cannot be combined directly to create
-a bitmask. Rather, the mask function should be used on these values.
+a bitmask. Rather, the
+.code mask
+function should be used on these values.
-.TP
-Example:
+.TP* Example:
- ;; Enable LOG_EMERG and LOG_ALERT messages, suppressing all others
+.cblk
+ ;; Enable LOG_EMERG and LOG_ALERT messages,
+ ;; suppressing all others
(setlogmask (mask log-emerg log-alert))
-
-
-.SS The syslog function
-
-.TP
-Syntax:
-
- (syslog <priority> <format> <format-arg>*)
-
-.TP
-Description:
-
-This function is the interface to the syslog C function. The printf formatting
-capabilities of the function are not used; it follows the conventions of the
-TXR Lisp format function instead. Note in particular that the %m convention
-for interpolating the value of strerror(errno) is currently not supported.
-
-.SH WEB PROGRAMMING SUPPORT
-
-.SS Functions url-encode and url-decode
-
-.TP
-Syntax:
-
- (url-encode <string> [<space-plus-p>])
- (url-decode <string> [<space-plus-p>])
-
-.TP
-Description:
-
+.cble
+
+.coNP The @ syslog function
+.synb
+.mets (syslog < priority < format << format-arg *)
+.syne
+.desc
+This function is the interface to the
+.code syslog
+C function. The
+.code printf
+formatting capabilities of the function are not used;
+the
+.meta format
+argument follows the conventions of the TXR Lisp
+.code format
+function instead. Note in particular that
+the
+.code %m
+convention for interpolating the value of strerror(errno) which is
+available in some versions of the
+.code syslog
+C function is currently not supported.
+
+Note that syslog messages are not newline-terminated.
+
+.SS* Web Programming Support
+
+.coNP Functions @ url-encode and @ url-decode
+.synb
+.mets (url-encode < string <> [ space-plus-p ])
+.mets (url-decode < string <> [ space-plus-p ])
+.syne
+.desc
These functions convert character strings to and from a form which is suitable
for embedding into the request portions of URL syntax.
@@ -14947,12 +23037,15 @@ character. Spaces and control characters are also encoded, as are all byte
values greater than or equal to 127 (7F hex). The printable ASCII characters
which are percent-encoded consist of this set:
+.cblk
:/?#[]@!$&'()*+,;=%
+.cble
More generally, strings can consists of Unicode characters, but the URL
encoding consists only of printable ASCII characters. Unicode characters in the
original string are encoded by expanding into UTF-8, and applying
-percent-encoding the UTF-8 bytes, which are all in the range 0x80-0xFF.
+percent-encoding the UTF-8 bytes, which are all in the range
+.codn \exx80-\exxFF .
Decoding is the reverse process: reconstituting the UTF-8 byte sequence
specified by the URL-encoding, and then decoding the UTF-8 sequence into the
@@ -14960,483 +23053,813 @@ string of Unicode characters.
There is an additional complication: whether or not to encode spaces as plus,
and to decode plus characters to spaces. In encoding, if spaces are not encoded
-to the plus character, then they are encoded as %20, since spaces are reserved
+to the plus character, then they are encoded as
+.codn %20 ,
+since spaces are reserved
characters that must be encoded. In decoding, if plus characters are not
decoded to spaces, then they are left alone: they become plus characters in the
decoded string.
-The url-encode function performs the encoding process. If the space-plus-p
-argument is omitted or specified as nil, then spaces are encoded as %20.
-If the argument is a value other than nil, then spaces are encoded as the
-character + (plus).
-
-The url-decode function performs the decoding process. If the space-plus-p
-argument is omitted or specified as nil, then + (plus) characters in the
-encoded data are retained as + characters in the decoded strings. Otherwise,
+The
+.code url-encode
+function performs the encoding process. If the
+.code space-plus-p
+argument is omitted or specified as
+.codn nil ,
+then spaces are encoded as
+.codn %20 .
+If the argument is a value other than
+.codn nil ,
+then spaces are encoded as the
+character
+.code +
+.codn (plus) .
+
+The
+.code url-decode
+function performs the decoding process. If the
+.code space-plus-p
+argument is omitted or specified as
+.codn nil ,
+then
+.code +
+.code (plus)
+characters in the
+encoded data are retained as
+.code +
+characters in the decoded strings. Otherwise,
plus characters are converted to spaces.
-.SS Functions html-encode and html-decode
-
-.TP
-Syntax:
-
- (html-encode <text-string>)
- (html-decode <html-string>)
-
-.TP
-Description:
-
-The html-encode and decode functions convert between an HTML and raw
-representation of of text.
-
-The html-encode function returns a string which is based on the content of
-<text-string>, but in which all characters which have special meaning in HTML
-have been replaced by special HTML codes for representing those characters.
+.coNP Functions @ html-encode and @ html-decode
+.synb
+.mets (html-encode << text-string )
+.mets (html-decode << html-string )
+.syne
+.desc
+The
+.code html-encode
+and
+.code html-decode
+functions convert between an HTML and raw
+representation of of text.
+
+The
+.code html-encode
+function returns a string which is based on the content of
+.metn text-string ,
+but in which all characters which have special meaning in HTML
+have been replaced by HTML codes for representing those characters literally.
The returned string is the HTML-encoded verbatim representation of
-<text-string>.
-
-The html-decode function converts <html-string>, which may contain HTML
-character encodings, into a string which contains the characters represented
-by those encodings.
-
-The function composition (html-decode (html-encode text)) returns a string
-which is equal to text.
-
-The reverse composition (html-encode (html-decode html)) does not necessarily
-return a string equal to text.
-
-For instance if html is the string "<p>Hello, world&#33;</p>",
-then html-decode produces "<p>Hello, world!</p>". Then, html-encode
-produces "&lt;p&gt;Hello, world!&lt;/p&gt;".
-
-.SH FILTER MODULE
-
+.metn text-string .
+
+The
+.code html-decode
+function converts
+.metn html-string ,
+which may contain HTML
+character encodings, into a string which contains the actual characters
+represented by those encodings.
+
+The function composition
+.code (html-decode (html-encode text))
+returns a string which is equal to
+.codn text .
+
+The reverse composition
+.code (html-encode (html-decode html))
+does not necessarily return a string equal to
+.codn html .
+
+For instance if html is the string
+.strn "<p>Hello, world&#33;</p>" ,
+then
+.code html-decode
+produces
+.strn "<p>Hello, world!</p>" .
+From this,
+.code html-encode
+produces
+.strn "&lt;p&gt;Hello, world!&lt;/p&gt;" .
+
+.SS* Filter Module
The filter module provides a trie (pronounced "try") data structure,
which is suitable for representing dictionaries for efficient filtering.
-Dictionaries are unordered collections of keys, which are strings, which
+Dictionaries are unordered collections of keys, which are strings, which
have associated values, which are also strings. A trie can be used to filter
text, such that keys appearing in the text are replaced by the corresponding
values. A trie supports this filtering operation by providing an efficient
prefix-based lookup method which only looks at each input character ones, and
which does not require knowledge of the length of the key in advance.
-.SS Function make-trie
-
-.TP
-Syntax:
-
+.coNP Function @ make-trie
+.synb
(make-trie)
-
-.TP
-Description:
-
-This function creates an empty trie. There is no special data type for
+.syne
+.desc
+The
+.code make-trie
+function creates an empty trie. There is no special data type for
a trie; a trie is some existing type such as a hash table.
-.SS Function trie-add
-
-.TP
-Syntax:
-
- (trie-add <trie> <key> <value>)
-
-.TP
-Description:
-
-The trie-add function adds the string <key> to the trie, associating
-it with <value>. If <key> already exists in <trie>, then the value
-is updated with <value>.
+.coNP Function @ trie-add
+.synb
+.mets (trie-add < trie < key << value )
+.syne
+.desc
+The
+.code trie-add
+function adds the string
+.meta key
+to the trie, associating
+it with
+.metn value .
+If
+.meta key
+already exists in
+.metn trie ,
+then the value is updated with
+.metn value .
-The <trie> must be a trie that has not been compressed with trie-compress.
+The
+.meta trie
+must not have been compressed with
+.metn trie-compress .
A trie can contain keys which are prefixes of other keys. For instance
-it can contain "dog" and "dogma". When a trie is used for matching
+it can contain
+.str dog
+and
+.strn dogma .
+When a trie is used for matching
and substitution, the longest match is used. If the input presents
-the text "doggy", then the match is "dog". If the input is "dogmatic",
-then "dogma" matches.
-
-
-.SS Function trie-compress
-
-.TP
-Syntax:
-
- (trie-compress <trie>)
-
-.TP
-Description:
-
-The trie-compress function changes the representation of <trie> to
-a representation which occupies less space and supports faster lookups.
-The new representation is returned.
-
-The compressed representation of a trie does not support the trie-add function.
+the text
+.strn doggy ,
+then the match is
+.strn dog .
+If the input is
+.strn dogmatic ,
+then
+.str dogma
+matches.
+
+.coNP Function @ trie-compress
+.synb
+.mets (trie-compress << trie )
+.syne
+.desc
+The
+.code trie-compress
+function changes the representation of
+.meta trie
+to a representation which occupies less space and supports faster lookups.
+The new representation is returned.
+
+The compressed representation of a trie does not support the
+.code trie-add
+function.
-This function destructively manipulates <trie>, and may return an object
-that is the same object as <trie>, or it may return a different object,
-while at the same time still modifying the internals of <trie>.
-Consequently, the program should not retain the input object <trie>,
+This function destructively manipulates
+.metn trie ,
+and may return an object
+that is the same object as
+.codn trie ,
+or it may return a different object,
+while at the same time still modifying the internals of
+.metn trie .
+Consequently, the program should not retain the input object
+.codn trie ,
but use the returned object in its place.
-.SS Function trie-lookup-begin
-
-.TP
-Syntax:
-
- (trie-lookup-begin <trie>)
-
-.TP
-Description:
-
-The trie-lookup-begin function returns a context object for performing
-an open-coded lookup traversal of a trie. The <trie> argument
-is expected to be a trie that was created by the make-trie function.
-
-.SS Function trie-lookup-feed-char
-
-.TP
-Syntax:
-
- (trie-lookup-feed-char <trie-context> <char>)
-
-.TP
-Description:
+.coNP Function @ trie-lookup-begin
+.synb
+.mets (trie-lookup-begin << trie )
+.syne
+.desc
+The
+.code trie-lookup-begin
+function returns a context object for performing
+an open-coded lookup traversal of a trie. The
+.meta tri
+argument
+is expected to be a trie that was created by the
+.code make-trie
+function.
-The trie-lookup-feed-char function performs a one character step in a trie
-lookup. The <trie-context> argument must be a trie contxt returned
-by trie-lookup-begin, or by some previous call to trie-lookup-feed-char.
-The <char> argument is the character to search for.
+.coNP Function @ trie-lookup-feed-char
+.synb
+.mets (trie-lookup-feed-char < trie-context << char )
+.syne
+.desc
+The
+.code trie-lookup-feed-char
+function performs a one character step in a trie
+lookup. The
+.meta trie-context
+argument must be a trie contxt returned
+by
+.metn trie-lookup-begin ,
+or by some previous call to
+.codn trie-lookup-feed-char .
+The
+.meta char
+argument is the next character to match.
If the lookup is successful (the match through the trie can continue
with the given character) then a new trie context object is returned.
The old trie context remains valid.
-If the lookup is unsuccessful, nil is returned.
+If the lookup is unsuccessful,
+.code nil
+is returned.
Note: determining whether a given string is stored in a trie can be
performed looking up every character of the string successively
-with trie-lookup-feed-char, using the newly returned context
+with
+.codn trie-lookup-feed-char ,
+using the newly returned context
for each successive operation. If every character is found, it means
that either that exact string is found in the trie, or a prefix.
The ambiguity can be resolved by testing whether the trie has a value
-at the last node using tree-value-at. For instance, if "catalog"
-is inserted into an empty trie with value "foo", then "cat" will look up
-successfully, being a prefix of "catalog"; however, the value at "cat" is nil.
-
-.SS Function tree-value-at
-
-.TP
-Syntax:
-
- (trie-value-at <trie-context>)
-
-.TP
-Description:
-
-The trie-value-at function returns the value stored at the node in
-in the trie given by <trie-context>. Nodes which have not been given
-a value hold the value nil.
-
-.SS Function filter-string-tree
-
-.TP
-Syntax:
-
- (filter-string-tree <filter> <obj>)
-
-.TP
-The filter-string-tree a tree structure similar to <obj>, in which all of the
-string atoms have been filtered through <filter>.
-
-The <obj> argument is a string tree structure: either the symbol nil, denoting
-an empty structure; a string; or a list of tree structures. If <obj> is
-nil, then filter-string-tree returns nil.
-
-The <filter> argument is a filter: it is either a trie, a function, or nil.
-If <filter> is nil, then filter-string-trie just returns <obj>.
+at the last node using
+.codn tree-value-at .
+For instance, if
+.str catalog
+is inserted into an empty trie with value
+.strn foo ,
+then
+.str cat
+will look up successfully, being a prefix of
+.strn catalog ;
+however, the value at
+.str cat
+is
+.codn nil ,
+indicating that
+.str cat
+is only a prefix of one or more entries in the trie.
+
+.coNP Function tree-value-at
+.synb
+.mets (trie-value-at << trie-context )
+.syne
+.desc
+The
+.code trie-value-at
+function returns the value stored at the node in
+in the trie given by
+.metn trie-context .
+Nodes which have not been given
+a value hold the value
+.codn nil .
+
+.coNP Function @ filter-string-tree
+.synb
+.mets (filter-string-tree < filter << obj )
+.syne
+.desc
+The
+.code filter-string-tree
+a tree structure similar to
+.metn obj ,
+in which all of the
+string atoms have been filtered through
+.metn filter .
+
+The
+.meta obj
+argument is a string tree structure: either the symbol
+.codn nil ,
+denoting an empty structure; a string; or a list of tree structures. If
+.meta obj
+is
+.codn nil ,
+then
+.code filter-string-tree
+returns
+.codn nil .
+
+The
+.meta filter
+argument is a filter: it is either a trie, a function, or nil.
+If
+.meta filter
+is
+.codn nil ,
+then
+.code filter-string-trie
+just returns
+.metn obj .
-If <filter> is a function, it must be a function that can be called
+If
+.meta filter
+is a function, it must be a function that can be called
with one argument. The strings of the string tree are filtered by passing
each one into the function and substituting the return value into the
corresponding place in the returned structure.
-Otherwise if <filter> is a trie, then this trie is used for filtering,
+Otherwise if
+.meta filter
+is a trie, then this trie is used for filtering,
the string elements similarly to a function. For each string, a new
string is returned in which occurrences of the keys in the trie are
replaced by the values in the trie.
-.SS Function filter-equal
-
-.TP
-Syntax:
-
- (filter-equal <filter-1> <filter-2> <obj-1> <obj-2>)
-
-.TP
-Description:
-
-The filter-equal function tests whether two string trees are equal
-under the given filters.
+.coNP Function @ filter-equal
+.synb
+.mets (filter-equal < filter-1 < filter-2 < obj-1 << obj-2 )
+.syne
+.desc
+The
+.code filter-equal
+function tests whether two string trees are equal
+under the given filters.
The precise semantics can be given by this expression:
- (equal (filter-string-tree <filter-1> <obj-1>)
- (filter-string-tree <filter-2> <obj-2>))
-
-The string tree <obj-1> is filtered through <filter-1>, as if
-by the filter-string-tree function, and similarly, <obj-2> is
-filtered through <filter-2>. The resulting structures are compared
-using equal, and the result of that is returned.
-
-.SH ACCESS TO TXR PATTERN LANGUAGE FROM LISP
-
-.SS Function match-fun
-
-.TP
-Syntax:
-
- (match-fun <name> <args> <input> <files>)
-
-.TP
-Description:
-
-The match-fun function invokes a txr pattern function whose name is
-given by the <name>, which must be a symbol.
-
-The <args> argument is a list of expressions. The expressions may be symbols
+.cblk
+.mets (equal (filter-string-tree < filter-1 << obj-1 )
+.mets \ \ \ \ \ \ (filter-string-tree < filter-2 << obj-2 ))
+.cble
+
+The string tree
+.meta obj-1
+is filtered through
+.metn filter-1 ,
+as if by the
+.code filter-string-tree
+function, and similarly,
+.meta obj-2
+is
+filtered through
+.metn filter-2 .
+The resulting structures are compared
+using
+.codn equal ,
+and the result of that is returned.
+
+.SS* Access To TXR Pattern Language From Lisp
+.coNP Function match-fun
+.synb
+.mets (match-fun < name < args < input << files )
+.syne
+.desc
+The
+.code match-fun
+function invokes a TXR pattern function whose name is
+given by
+.metn name ,
+which must be a symbol.
+
+The
+.meta args
+argument is a list of expressions. The expressions may be symbols
which will be interpreted as pattern variables, and may be bound or unbound.
If they are not symbols, then they are treated as expressions (of the
pattern language, not TXR Lisp) and evaluated accordingly.
-The <input> argument is a list of strings, which may be lazy. It represents the
+The
+.meta inpu
+argument is a list of strings, which may be lazy. It represents the
lines of the text stream to be processed.
-The <files> argument is a list of filename specifications, which follow
+The
+.meta file
+argument is a list of filename specifications, which follow
the same conventions as files given on the TXR command line. If the pattern
-function uses the @(next) directive, it can process these additional files.
-
-The match-fun function's return value falls into three cases. If there is a
-match failure, it returns nil. Otherwise it returns a cons cell. The car field
-of the cons cell holds the list of captured bindings. The cdr of the cons cell
-is one of two values. If the entire input was processed, the cdr field holds
-the symbol t. Otherwise it holds another cons cell whose car is the remainder
-of the list of lines which were not matched, and the cdr is the line number.
-
-.TP
-Example:
-
+function uses the
+.code @(next)
+directive, it can process these additional files.
+
+The
+.code match-fun
+function's return value falls into three cases. If there is a
+match failure, it returns
+.codn nil .
+Otherwise it returns a cons cell. The
+.code car
+field
+of the cons cell holds the list of captured bindings. The
+.code cdr
+of the cons cell is one of two values. If the entire input was processed, the
+cdr field holds the symbol
+.codn t .
+Otherwise it holds another cons cell whose
+.code car
+is the remainder of the list of lines which were not matched, and whose
+.code cdr
+is the line number.
+
+.TP* Example:
+
+.cblk
@(define foo (x y))
@x:@y
@line
@(end)
@(do
(format t "~s\en"
- (match-fun 'foo '(a b) '("alpha:beta" "gamma" "omega") nil)))
+ (match-fun 'foo '(a b)
+ '("alpha:beta" "gamma" "omega") nil)))
Output:
(((a . "alpha") (b . "beta")) ("omega") . 3)
-
-In the above example, the pattern function foo is called with arguments (a b).
-These are unbound variables, so they correspond to parameters x and y
-of the function. If x and y get bound, those values propagate to a and b.
-The data being matched consists of the lines "alpha:beta", "gamma" and
-"omega". Inside foo, x and y bind to "alpha" and "beta", and then the
-line variable binds t "gamma". The input stream is left with "omega".
-
-Hence, the return value consists of the bindings of x and y transferred to a
-and b, and the second cons cell giving information about the rest of the
-stream: it is the part starting at "omega", which is line 3. Note that the
-binding for for line variable does not propagate out of the pattern function
-foo; it is local inside it.
-
-.SH QUOTE/QUASIQUOTE OPERATOR SYNTAX
-
-.SS Operator quote
-
-.TP
-Syntax:
-
- (quote <form>)
-
-.TP
-Description:
-
-The quote operator, when evaluated, suppresses the evaluation of <form>,
-and instead returns <form> itself as an object. For example, if <form>
-is a symbol, then <form> is not evaluated to the symbol's value; rather
+.cble
+
+In the above example, the pattern function
+.code foo
+is called with arguments
+.codn (a b) .
+These are unbound variables, so they correspond to parameters
+.code x
+and
+.code y
+of the function. If
+.code x
+and
+.code y
+get bound, those values propagate to
+.code a
+and
+.codn b .
+The data being matched consists of the lines
+.strn alpha:beta ,
+.str gamma
+and
+.strn omega .
+Inside
+.codn foo,
+.code x
+and
+.code y
+bind to
+.str alpha
+and
+.strn beta ,
+and then the line variable binds to
+.strn gamma .
+The input stream is left with
+.strn omega .
+
+Hence, the return value consists of the bindings of
+.code x
+and
+.code y
+transferred to
+.code a
+and
+.codn b ,
+and the second cons cell which gives information about the rest of the
+stream: it is the part starting at
+.strn omega ,
+which is line 3. Note that the binding for the
+.code line
+variable does not propagate
+out of the pattern function
+.codn foo ;
+it is local inside it.
+
+.SS* Quote/Quasiquote Operator Syntax
+.coNP Operator @ quote
+.synb
+.mets (quote << form )
+.syne
+.desc
+The
+.code quote
+operator, when evaluated, suppresses the evaluation of
+.metn form ,
+and instead returns
+.meta form
+itself as an object. For example, if
+.meta form
+is a symbol, then
+.meta form
+is not evaluated to the symbol's value; rather
the symbol itself is returned.
-Note: when the quote syntax '<form> is used it is translated to
-(quote <form>).
+Note: the quote syntax
+.cblk
+.meti >> ' <form>
+.cble
+is translated to
+.cblk
+.meti (quote << form ).
+.cble
-.TP
-Example:
+.TP* Example:
+.cblk
(quote a) ;; yields a
(quote (+ 2 2)) ;; yields (+ 2 2), not 4.
+.cble
+
+.coNP Macro @ qquote
+.synb
+.mets (qquote << form )
+.syne
+.desc
+The
+.code qquote
+(quasi-quote) macro operator implements a notation for convenient
+list construction. If
+.meta form
+is an atom, or a list structure which
+does not contain any
+.code unquote
+or
+.code splice
+operators, then
+.cblk
+.meti (qquote << form )
+.cble
+is equivalent to
+.cblk
+.meti (qquote << form ).
+.cble
-.SS Macro qquote
-
-.TP
-Syntax:
-
- (qquote <form>)
-
-.TP
-Description:
-
-The qquote (quasi-quote) macro operator implements a notation for convenient
-list construction. If <form> is an atom, or a list structure which
-does not contain any unquote or splice operators, then (qquote <form>)
-is equivalent to (quote <form>).
-
-If <form>, however, is a list structure which contains unquote or splice
+If
+.metn form ,
+however, is a list structure which contains
+.code unquote
+or
+.code splice
operators, then the substitutions implied by those operators are performed
-on <form>, and the qquote operator returns the resulting structure.
+on
+.metn form ,
+and the
+.code qquote
+operator returns the resulting structure.
+
Note: how the qquote operator actually works is that it is compiled into
-code: a Lisp expression which computes the resulting structure when evaluated.
+code. It becomes a Lisp expression which, when evaluated, computes the
+resulting structure.
-A qquote can contain another qquote. If an unquote or splice operator occurs
-within a nested qquote, it belongs to that qquote, and not to the outer one.
+A
+.code qquote
+can contain another
+.codn qquote .
+If an
+.code unquote
+or
+.code splice
+operator occurs
+within a nested
+.codn qquote ,
+it belongs to that
+.codn qquote ,
+and not to the outer one.
However, an unquote operator which occurs inside another one belongs one level
-higher. For instance in (qquote (qquote (unquote (unquote x)))),
-the leftmost qquote belongs with the rightmost unquote, and the inner
-qquote and unquote belong together. When the outer qquote is evaluated,
-it will insert the x, resulting in the value (qquote (unquote <val-x>)).
-where <val-x> represents the object which is the value of variable x. If this
-resulting qquote value is evaluated again as Lisp syntax, then it
-will yield <val-val-x>, where <val-val-x> denotes the value of <val-x>
-when <val-x> is treated as a Lisp expression and evaluated.
-
-.TP
-Examples:
-
+higher. For instance in
+
+.cblk
+ (qquote (qquote (unquote (unquote x))))
+.cble
+
+the leftmost
+.code qquote
+belongs with the rightmost unquote, and the inner
+.code qquote
+and
+.code unquote
+belong together. When the outer
+.code qquote
+is evaluated,
+it will insert the value of
+.codn x ,
+resulting in the object
+.codn (qquote (unquote [value-of-x])) .
+If this resulting qquote value is evaluated again as Lisp syntax, then it will
+yield
+.codn [value-of-value-of-x] ,
+the value of
+.code [value-of-x]
+when treated as a Lisp expresion and evaluated.
+
+.TP* Examples:
+
+.cblk
(qquote a) -> a
(qquote (a b c)) -> (a b c)
- (qquote (1 2 3 (unquote (+ 2 2) (+ 2 3)))) -> (1 2 3 4 (+ 2 3))
+ (qquote (1 2 3 (unquote (+ 2 2)) (+ 2 3))) -> (1 2 3 4 (+ 2 3))
(qquote (unquote (+ 2 2))) -> 4
-
-In the second-to-last example, the 1 2 3 and the (+ 2 3) were taken verbatim.
-But the (unquote (+ 2 2)) operator caused the evaluation of (+ 2 2) and the
-substitution of the resulting value.
-
-The last example shows that <form> can itself be an unquote operator.
-However, note: (quote (splice <form>)) is not valid.
-
-Note: a way to understand the nesting behavior is a model of quasi-quote
-expansion which recursively compiles any nested quasi quotes first, and then
-treats the result of their expansion. For instance, in the processing of
-(qquote (qquote (unquote (unquote x)))), the quote operator
-finds the internal (qquote ...) and compiles it to code. During that recursive
-compilation, the syntax (unquote (unquote x)) is encountered.
-The inner quote processes the outer unquote which belongs to it,
-and the (unquote x) becomes material embedded in the compilation,
-which will then be found when the outer quasiquote takes the inner
-compilation and processes its interior.
-
-.TP
-Dialect note:
+.cble
+
+In the second-to-last example, the
+.code 1 2 3
+and the
+.code (+ 2 3)
+are quoted verbatim.
+Whereas the
+.code (unquote (+ 2 2))
+operator caused the evaluation of
+.code (+ 2 2)
+and the substitution of the resulting value.
+
+The last example shows that
+.meta form
+can itself (the entire argument of
+.codn qquote )
+can be an unquote operator.
+However, note:
+.code (quote (splice form))
+is not valid.
+
+Note: a way to understand the nesting behavior is a via a possible model of
+quasi-quote expansion which recursively compiles any nested quasi quotes first,
+and then treats the result of their expansion. For instance, in the processing
+of
+
+.cblk
+ (qquote (qquote (unquote (unquote x))))
+.cble
+
+the
+.code qquote
+operator first encounters the
+embedded
+.code (qquote ...)
+and compiles it to code. During that recursive
+compilation, the syntax
+.code (unquote (unquote x))
+is encountered. The inner quote
+processes the outer unquote which belongs to it, and the inner
+.code (unquote x)
+becomes material that is embedded verbatim in the compilation, which will then
+be found when the recursion pops back to the outer quasiquote, which will
+then traverse the result of the inner compilation and find the
+.codn (unquote x) .
+
+.TP* "Dialect note:"
In Lisp dialects which have a published quasiquoting operator syntax, there is
the expectation that the quasiquote read syntax corresponds to it. That is to
-say, that for instance the read syntax ^(a b ,c) is translated to
-(qquote b (unquote c)).
-
-In TXR Lisp, this is not true! Although ^(b b ,c) is translated to a
-quasiquoting macro, it is an internal one, not based on the public qquote,
-unquote and splice symbols.
+say, that for instance the read syntax
+.code ^(a b ,c)
+is expected translated to
+.codn (qquote b (unquote c)) .
+
+In TXR Lisp, this is not true! Although
+.code ^(b b ,c)
+is translated to a
+quasiquoting macro, it is an internal one, not based on the public
+.codn qquote ,
+.code unquote
+and
+.code splice
+symbols being documentd here.
This idea exists for hygiene. The quasiquote read syntax is not confused
-by the presence of the symbols qquote, unquote or splice in the template,
-since it doesn't treat them specially.
+by the presence of the symbols
+.codn qquote ,
+.code unquote
+or
+.code splice
+in the template, since it doesn't treat them specially.
This also allows programmers to use the quasiquote read syntax to construct
quasiquote macros. For instance
+.cblk
^(qquote (unquote ,x)) ;; does not mean ^^,x
-
-To the quasiquote reader, the qquote and unquote symbols mean nothing special,
-and so this syntax simply means that if the value of x is foo, the result will
-be (qquote (unquote foo)).
+.cble
+
+To the quasiquote reader, the
+.code qquote
+and
+.code unquote
+symbols mean nothing special,
+and so this syntax simply means that if the value of
+.code x
+is
+.codn foo ,
+the result will be
+.codn (qquote (unquote foo)) .
The form's expansion is actually this:
+.cblk
(sys:qquote (qquote (unquote (sys:unquote x))))
-
-the sys:qquote macro recognizes sys:unquote embedded in the form, and
-the other symbols not in the sys: package are just static template material.
-
-.SS Operator unquote
-
-.TP
-Syntax:
-
- (qquote (... (unquote <form>) ...))
-
- (qquote (unquote <form>))
-
-.TP
-Description:
-
-The unquote operator is not an operator per se. The unquote symbol has no
+.cble
+
+the
+.code sys:qquote
+macro recognizes
+.code sys:unquote
+embedded in the form, and
+the other symbols not in the
+.code sys:
+package are just static template material.
+
+The
+.code sys:quote
+macro and its associated
+.code sys:unquote
+and
+.code sys:splice
+operators work exactly like their ordinary counterparts. So in effect, TXR has
+two nearly identical, independent quasi-quote implementations, one of which is
+tied to the read syntax, and one of which isn't. This is useful for writing
+quasiquotes which write quasiquotes.
+
+.coNP Operator @ unquote
+.synb
+.mets (qquote (... (unquote << form ) ...))
+.mets (qquote (unquote << form ))
+.syne
+.desc
+The
+.code unquote
+operator is not an operator
+.I per
+.IR se .
+The
+.code unquote
+symbol has no
binding in the global environment. It is a special syntax that is recognized
-within a qquote form, to indicate forms within the quasiquote which are to be
+within a
+.code qquote
+form, to indicate forms within the quasiquote which are to be
evaluated and inserted into the resulting structure.
-The variant (qquote (unquote <form>)) is equivalent to <form>: the
-qquote and unquote "cancel out".
-
-Nesting of qquotes and unquotes is explained in the qquote operator.
-
-.SS Operator splice
-
-.TP
-Syntax:
-
- (qquote (... (splice <form>) ...))
-
-.TP
-Description:
-
-The splice operator is not an operator per se. The splice symbol has no
+The syntax
+.cblk
+.meti (qquote (unquote << form ))
+.cblk
+is equivalent to
+.metn form :
+the
+.code qquote
+and
+.code unquote
+"cancel out".
+
+.coNP Operator splice
+.synb
+.mets (qquote (... (splice << form ) ...))
+.syne
+.desc
+The
+.code splice
+operator is not an operator
+.I per
+.IR se .
+The
+.code splice
+symbol has no
binding in the global environment. It is a special syntax that is recognized
-within a qquote form, to indicate forms within the quasiquote which are to be
+within a
+.code qquote
+form, to indicate forms within the quasiquote which are to be
evaluated and inserted into the resulting structure.
-The variant (qquote (unquote <form>)) is not permitted and raises
-an exception if evaluated. The splice syntax must occur within a list,
-and not in the dotted position.
-
-The splice form differs from unquote in that (splice <form>)
-requires that <form> must evaluate to a list. That list is
-integrated into the surrounding list.
-
-Nesting of qquotes and unquotes is explained in the qquote operator.
-
-.SH MACROS
-
+The syntax
+.cblk
+.meti (qquote (splice << form ))
+.cble
+is not permitted and raises an exception if evaluated. The
+.code splice
+syntax must occur within a list, and not in the dotted position.
+
+The
+.code splice
+form differs from unquote in that
+.cblk
+.meti (splice << form )
+.cble
+requires that
+.meta form
+must evaluate to a list. That list is
+integrated into the surrounding list.
+
+.SS* Macros
TXR Lisp supports structural macros. TXR's model of macroexpansion is that TXR
Lisp code is processed in two phases: the expansion phase and the evaluation
phase. The expansion phase is invoked on Lisp code early during the processing
-of source code. For instance when a TXR File containing a @(do ...) directive
+of source code. For instance when a TXR File containing a
+.code @(do ...)
+directive
is loaded, expansion of the Lisp forms are its arguments takes place during the
parsing of the entire source file, and is complete before any of the code in
-that file is executed. If and when the @(do ...) form is later executed,
-the expanded forms are evaluated.
+that file is executed. If the
+.code @(do ...)
+form is later executed,
+the expanded forms are then evaluated.
TXR Lisp also supports symbol macros, which are symbolic forms that stand
for forms, with which they are replaced at macro expansion time.
-When Lisp data is processed as code by the eval function, it is first expanded,
+When Lisp data is processed as code by the
+.code eval
+function, it is first expanded,
and so processed in its entirety in the expansion phase. Then it is processed
in the evaluation phase.
-.SS Macro parameter lists.
+.coNP Macro parameter lists
TXR macros support destructuring, similarly to Common Lisp macros.
This means that macro parameter lists are like function argument lists,
@@ -15444,253 +23867,407 @@ but support nesting. A macro parameter list can specify a nested parameter
list in every place where a function argument list allows only a parameter
name. For instance, consider this macro parameter list:
+.cblk
((a (b c)) : (c frm) ((d e) frm2 de-p) . g)
-
-The top level of this list has four elements: the mandatory parameter (a (b
-c)), the optional parameter c (with default init form frm), the optional
-parameter (d e) with default init form frm2 and presence-indicating variable
-de-p, and the parameter g which captures trailing arguments.
-
-Note that some of the parameters are compounds: (a (b c)) and (d e).
+.cble
+
+The top level of this list has four elements: the mandatory parameter
+.codn (a (b c)) ,
+the optional parameter
+.code c
+(with default init form
+.codn frm ),
+the optional parameter
+.code (d e)
+(with default init form
+.code frm2
+and presence-indicating variable
+.codn de-p ),
+and the dot-position parameter
+.code g
+which captures trailing arguments.
+
+Note that some of the parameters are compounds:
+.code (a (b c))
+and
+.codn (d e) .
These compounds express nested macro parameter lists.
Macro parameter lists match a similar tree structure to their own.
-For instance a mandatory parameter (a (b c)) matches a structure like
-(1 (2 3)), such that the parameters a, b and c will end up bound
-to 1, 2, and 3, respectively.
-
-The binding strictness is relaxed for optional parameters. If (a (b c))
-is optional, and the argument is, say, (1), then a gets 1, and b and c
-receive nil.
-
-Macro parameter lists also support two special keywords, namely :env and :whole.
-
-The parameter list (:whole x :env y) will bind parameter x to the entire
-macro form, and y will bind parameter y to the macro environment.
-(Note: Macro environments currently do not do anything in TXR Lisp; this
-functionality is for future expansion.) The :whole and :env notation
-can occur anywhere in a macro parameter list.
-
-.SS Operator macro-time
-
-.TP
-Syntax:
-
- (macro-time {<form>}*)
-
-.TP
-Description:
-
-The macro-time operator has a syntax similar to a progn form. The forms are
-evaluated from left to right, and the resulting value is that of the last form.
+For instance a mandatory parameter
+.code (a (b c))
+matches a structure like
+.codn (1 (2 3)) ,
+such that the parameters
+.codn a ,
+.code b
+and
+.code c
+will end up bound
+to
+.codn 1 ,
+.code 2
+and
+.codn 3 ,
+respectively.
+
+The binding strictness is relaxed for optional parameters. If
+.code (a (b c))
+is optional, and the argument is, say,
+.codn (1) ,
+then
+.code a
+gets
+.codn 1 ,
+and
+.code b
+and
+.code c
+receive
+.codn nil .
+
+Macro parameter lists also support two special keywords, namely
+.code :env
+and
+.codn :whole .
+
+The parameter list
+.codn (:whole x :env y)
+will bind parameter
+.code x
+to the entire
+macro form, and bind parameter
+.code y
+to the macro environment.
+The
+.code :whole
+and
+.code :env
+notation can occur anywhere in a macro parameter list.
+
+.coNP Operator @ macro-time
+.synb
+.mets (macro-time << form *)
+.syne
+.desc
+The
+.code macro-time
+operator has a syntax similar to the
+.code progn
+operator. Each
+.meta form
+is evaluated from left to right, and the resulting value is that of the last
+form.
-The special behavior of macro-time is that the evaluation takes place during
+The special behavior of
+.code macro-time
+is that the evaluation takes place during
the expansion phase, rather than during the evaluation phase.
-During the expansion phase, all macro-time expressions which occur in a context
+During the expansion phase, all
+.code macro-time
+expressions which occur in a context
that calls for evaluation are evaluated, and replaced by their quoted values.
-For instance (macro-time (list 1 2 3)) evaluates (list 1 2 3) to the object (1
-2 3) and the entire macro-time form is replaced by the quoted list '(1 2 3).
+For instance
+.code (macro-time (list 1 2 3))
+evaluates
+.code (list 1 2 3)
+to the object
+.code (1 2 3)
+and the entire
+.code macro-time
+form is replaced by that value, quoted:
+.codn '(1 2 3) .
If the form is evaluated again at evaluation-time, the resulting value will be
-that of the quote.
+that of the quote, in this case
+.codn (1 2 3) .
-macro-time forms do not see the surrounding lexical environment; the see only
+.code macro-time
+forms do not see the surrounding lexical environment; the see only
global function and variable bindings and macros.
-Note 1: macro-time is intended for defining helper functions and variables that
-are used by macros. A macro cannot "see" a defun function or defvar variable
-because defun and defvar forms are evaluated at evaluation time, which occurs
+Note 1:
+.code macro-time
+is intended for defining helper functions and variables that
+are used by macros. A macro cannot "see" a
+.code defun
+function or
+.code defvar
+variable
+because
+.code defun
+and
+.code defvar
+forms are evaluated at evaluation time, which occurs
after expansion time. The macro-time operator hoists the evaluation of these
-forms to macro-expansion time.
-
-Note 2: defmacro forms are implicitly in macro-time; they do not have to
-be wrapped with the macro-time operator. The macro-time operator doesn't have
+forms to macro-expansion time.
+
+Note 2:
+.code defmacro
+forms are implicitly in macro-time; they do not have to
+be wrapped with the
+.code macro-time
+operator. The
+.code macro-time
+operator doesn't have
to be used in programs whose macros do not make references to variables
or functions.
-.SS Operator defmacro
-
-.TP
-Syntax:
-
- (defmacro <name> (<param>* [: <opt-param>*] [. <rest-param>]) <body-form>*)
-
-.TP
-Description:
-
-The defmacro operator is evaluated at expansion time. It defines a
-macro-expander function under the name <name>, effectively creating
-a new operator.
+.coNP Operator @ defmacro
+.synb
+.mets (defmacro < name <> ( param * [: << opt-param * ] [. < rest-param ])
+.mets \ \ << body-form *)
+.syne
+.desc
+The
+.code defmacro
+operator is evaluated at expansion time. It defines a
+macro-expander function under the name
+.metn name ,
+effectively creating a new operator.
Note that the parameter list is a macro parameter list, and not a
-function parameter list. This means that each <param> can have not
-only the syntax <symbol> but it can itself be a parameter list.
-The corresponding argument is then treated as an argument list.
-Similarly, each symbol in the <opt-param> syntax can be an argument list.
-
-This nesting can be carried to an arbitrary depth.
+function parameter list. This means that each
+.meta param
+and
+.meta opt-param
+can be not only a symbol, but it can itself be a parameter list.
+The corresponding argument is then treated as a structure which
+matches that parameter list. This nesting of parameter lists
+can be carried to an arbitrary depth.
A macro is called like any other operator, and resembles a function. Unlike in
a function call, the macro receives the argument expressions themselves, rather
than their values. Therefore it operates on syntax rather than on values.
Also, unlike a function call, a macro call occurs in the expansion phase,
-rather than the evaluation phase.
+rather than the evaluation phase.
-The return value of the macro is is the macro expansion. It is substituted in
+The return value of the macro is the macro expansion. It is substituted in
place of the entire macro call form. That form is then expanded again;
it may itself be another macro call, or contain more macro calls.
-.TP
-Examples:
-
- ;; A macro to swap two places, such as variables.
- ;; (swap x y) will now exchange the contents of x and y.
-
- (defmacro swap (a b)
- (let ((temp (gensym)))
- ^(let ((,temp ,a))
- (set ,a ,b)
- (set ,b ,temp))))
-
-
- ;; dolist macro similar to Common Lisp's:
- ;;
- ;; The following will print 1, 2 and 3 on separate lines:
- ;; and return 42.
- ;;
- ;; (dolist (x '(1 2 3) 42)
- ;; (format t "~s\en"))
-
- (defmacro dolist ((var list : result) . body)
- (let ((i (my-gensym)))
- ^(for ((i ,list)) (i ,result) ((set i (cdr i)))
- (let ((,var (car i)))
- ,*body))))
-
-.SS Operator macrolet
-
-.TP
-Syntax:
+.TP* Examples:
- (macrolet ({(<name> <macro-style-params> <macro-body-form>*)}*)
- <body-form>*)
+.cblk
+ ;; A macro to swap two places, such as variables.
+ ;; (swap x y) will now exchange the contents
+ ;; of x and y.
-.TP
-Description:
-
-The macrolet binding operator extends the macro-time lexical environment
-by making zero or more new local macros visible.
-
-The operator symbol is followed by a list of macro definitions.
-Each definition is a form which begins with a name, followed by a macro
-parameter list, and zero or more forms. These macro definitions are similar
-to those globally defined by the defmacro operator, except that they
-are in a local environment, and do not capture any regular lexical scope.
-
-The macro definitions are followed by optional forms.
+ (defmacro swap (a b)
+ (let ((temp (gensym)))
+ ^(let ((,temp ,a))
+ (set ,a ,b)
+ (set ,b ,temp))))
-The macros thus defined are visible to the <body-form>-s.
-
-Forms inside the macro definitions such as the <macro-body-form>-s,
-and initializer forms appearing in <macro-style-params> are subject
+ ;; dolist macro similar to Common Lisp's:
+ ;;
+ ;; The following will print 1, 2 and 3
+ ;; on separate lines:
+ ;; and return 42.
+ ;;
+ ;; (dolist (x '(1 2 3) 42)
+ ;; (format t "~s\en"))
+
+ (defmacro dolist ((var list : result) . body)
+ (let ((i (my-gensym)))
+ ^(for ((i ,list)) (i ,result) ((set i (cdr i)))
+ (let ((,var (car i)))
+ ,*body))))
+.cble
+
+.coNP Operator @ macrolet
+.synb
+.mets (macrolet >> ({( name < macro-style-params << macro-body-form *)}*)
+.mets \ \ << body-form *)
+.syne
+.desc
+The
+.code macrolet
+binding operator extends the macro-time lexical environment
+by making zero or more new local macros visible.
+
+The
+.code macrolet
+symbol is followed by a list of macro definitions.
+Each definition is a form which begins with a
+.metn name ,
+followed by
+.meta macro-style-params
+which is a macro parameter list, and zero or more
+.metn macro-body-form s.
+These macro definitions are similar
+to those globally defined by the
+.code defmacro
+operator, except that they
+are in a local environment.
+
+The macro definitions are followed by optional
+.metn body-forms .
+The macros specified in the definitions are visible to these
+forms.
+
+Forms inside the macro definitions such as the
+.metn macro-body-form s,
+and initializer forms appearing in the
+.meta macro-style-params
+are subject
to macro-expansion in a scope in which none of the new macros being
defined are yet visible. Once the macro definitions are themselves
macro-expanded, they are placed into a new macro environment, which
-is then used for macro expanding the <body-form>-s.
+is then used for macro expanding the
+.metn body-form s.
-A macrolet form is fully processed in the expansion phase of a form, and is
-effectively replaced by progn form which contains expanded versions of
-<body-forms>-s, only. This expanded structure shows no evidence that any
+A
+.code macrolet
+form is fully processed in the expansion phase of a form, and is
+effectively replaced by
+.code progn
+form which contains expanded versions of
+.metn body-forms s.
+This expanded structure shows no evidence that any
macrolet forms ever existed in it. Therefore, it is impossible for the code
-evaluated in the bodies and parameter lists of macrolet macros to have any
-visibility to any surrounding lexical variable bindings, which are only
-instantiated in the evaluation phase, after expansion is done.
-
-.SS Function macro-form-p
-
-.TP
-Syntax:
-
- (macro-form-p <obj> [<env>])
-
-.TP
-Description:
-
-The macro-form-p function returns t if <obj> represents the syntax of
+evaluated in the bodies and parameter lists of
+.code macrolet
+macros to have any visibility to any surrounding lexical variable bindings,
+which are only instantiated in the evaluation phase, after expansion is done
+and macros no longer exist.
+
+.coNP Function @ macro-form-p
+.synb
+.mets (macro-form-p < obj <> [ env ])
+.syne
+.desc
+The
+.code macro-form-p
+function returns
+.code t
+if
+.meta obj
+represents the syntax of
a form which is a macro form: either a compound macro or a symbol macro.
-Otherwise it returns nil.
-
-A macro form will transform under macroexpand-1 or macroexpand; an object
-which isn't a macro form will not undergo expansion.
-
-The optional <env> parameter is a macroexpansion environment.
+Otherwise it returns
+.codn nil .
+
+A macro form is one that will transform under
+.code macroexpand-1
+or
+.codn macroexpand ;
+an object which isn't a macro form will not undergo expansion.
+
+The optional
+.meta env
+parameter is a macroexpansion environment.
A macroexpansion environment is passed down to macros and can be received
-via their special :env parameter. A macro can use this environment to
-determine whether a piece of syntax <obj> is a macro form in that
-environment.
-
-.TP
-Example:
-
- ;; macro which translates form to the form 'yes if it is a macro
- ;; form, otherwise to the form 'no.
+via their special
+.code :env
+parameter.
- (defmacro global (:env menv form)
- (if (macro-form-p form menv)
- ''yes ''no))
+.meta env
+is used by
+.code macro-form-p
+to determine whether
+.meta obj
+is a macro in a lexical macro environment.
- (macrolet ((local ()))
- (global (local))) ;; yields yes
+If
+.meta env
+is not specified or is
+.codn nil ,
+then
+.code macro-form-p
+only recognizes global macros.
- (global (local)) ;; yields no
+.TP* Example:
+.cblk
+ ;; macro which translates to 'yes if its
+ ;; argument is a macro from, or otherwise
+ ;; transforms to the form 'no.
-During macroexpansion, the global macro is handed the environment which
-it receives via :env menv. When the macro is invoked within the macrolet,
-this environment includes the macro-time lexical scope in which the
-local macro is defined. So when global checks whether the argument form
-(local) is a macro, the conclusion is yes: the (local) form is a macro
-call in that environment: macro-form-p yields t. When (global (local)) is
-invoked outside of the macrolet, no local macro is visible, and so macro-form-p
-yields nil.
+ (defmacro ismacro (:env menv form)
+ (if (macro-form-p form menv)
+ ''yes ''no))
-.SS Functions macroexpand-1 and macroexpand
+ (macrolet ((local ()))
+ (ismacro (local))) ;; yields yes
-.TP
-Syntax:
+ (ismacro (local)) ;; yields no
- (macroexpand-1 <obj> [<env>])
- (macroexpand <obj> [<env>])
+ (ismacro (ismacro foo)) ;; yields yes
+.cble
-.TP
-Description:
+During macro expansion, the global macro
+.code ismacro
+is handed the macro-expansion environment
+via
+.codn :env menv .
-If <obj> is a macro form (an object for which macro-form-p returns t),
+When the macro is invoked within the macrolet,
+this environment includes the macro-time lexical scope in which the
+.code local
+macro is defined. So when global checks whether the argument form
+.code (local)
+is a macro, the conclusion is yes: the (local) form is a macro
+call in that environment:
+.code macro-form-p
+yields
+.codn t .
+
+When
+.code (global (local))
+is invoked outside of the macrolet, no local macro is visible is
+there, and so
+.code macro-form-p
+yields
+.codn nil .
+
+.coNP Functions @ macroexpand-1 and @ macroexpand
+.synb
+.mets (macroexpand-1 < obj <> [ env ])
+.mets (macroexpand < obj <> [ env ])
+.syne
+.desc
+If
+.meta obj
+is a macro form (an object for which
+.code macro-form-p
+returns
+.codn t ),
these functions expand the macro form and return the expanded form.
-Otherwise, they return <obj>.
+Otherwise, they return
+.metn obj .
-macroexpand-1 performs a single expansion, expanding just the macro
-that is referenced by the symbol in the first position of <obj>,
+.code macroexpand-1
+performs a single expansion, expanding just the macro
+that is referenced by the symbol in the first position of
+.metn obj ,
and returns the expansion. That expansion may itself be a macro form.
-macroexpand performs an expansion, like macroexpand-1. If the result is
+.code macroexpand
+performs an expansion similar to
+.codn macroexpand-1 .
+If the result is
a macro form, then it expands that form, and keeps repeating this process
until the expansion yields a non-macro-form. That non-macro-form is then
returned.
-The optional <env> parameter is a macroexpansion environment.
+The optional
+.meta env
+parameter is a macroexpansion environment.
A macroexpansion environment is passed down to macros and can be received
-via their special :env parameter. The environment they receive is their
+via their special
+.code :env
+parameter. The environment they receive is their
lexically apparent macro-time environment in which local macros may be
visible. A macro can use this environment to "manually" expand some
form in the context of that environment.
-.TP
-Example:
+.TP* Example:
- ;; (foo x) expands x, and if x begins with a number, it removes
- ;; the number and returns the resulting form. Otherwise, it
- ;; returns the entire form.
+.cblk
+ ;; (foo x) expands x, and if x begins with a number,
+ ;; it removes the number and returns the resulting
+ ;; form. Otherwise, it returns the entire form.
(defmacro rem-num (:env menv some-form)
(let ((expanded (macroexpand some-form menv)))
@@ -15703,265 +24280,379 @@ Example:
(macrolet ((foo () '(1 list 42))
(bar () '(list 'a)))
(list (rem-num (foo)) (rem-num (bar)))))
+.cble
+
+The
+.code rem-num
+macro is able to expand the
+.code (foo)
+and
+.code (bar)
+forms it receives as
+the
+.code some-form
+argument, even though these forms use local macro that are only
+visible in their local scope. This is thanks to the macro
+environment passed to
+.codn rem-num .
+It is correctly able to work with the
+expansions
+.code (1 list 42)
+and
+.code (list 'a)
+to produce
+.code (list 42)
+and
+.code (list 'a)
+which evaluate to
+.code 42
+and
+.code a
+respectively.
+
+.coNP Operator @ defsymacro
+.synb
+.mets (defsymacro < sym << form )
+.syne
+.desc
-The rem-num macro is able to expand the (foo) and (bar) forms it receives as
-the some-form argument, using the local macro that is lexically apparent
-where those forms are passed, and is correctly able to work with the
-expansions (1 list 42) and (list 'a) to produce (list 42) and (list 'a)
-which evaluate to 42 and a respectively.
-
-.SS Operator defsymacro
-
-.TP
-Syntax:
-
- (defsymacro <sym> <form>)
-
-.TP
-Description:
-
-The defsymacro operator binds a symbol macro in the global environment.
-A defsymacro form is implicitly executed at expansion time, and thus need
-not be wrapped in a macro-time form.
-
-The visibility of a symbol macro binding for <sym> specifies that occurrences
-of <sym> in program code which are to be evaluated, or which denote places
-which are the targets of assignments, are subject to a replacement by <form>.
+A
+.code defsymacro
+form introduces a symbol macro: a symbol macro is a parameterless
+substitution keyed to a symbol. In contexts where a symbol macro
+definition of
+.meta sym
+is visible, if the form
+.meta sym
+appears such that its evaluation is called for, it is subject
+to replacement by
+.metn form .
+After replacement takes place,
+.meta form
+itself is then processed for further replacement of macros and
+symbol macros.
+
+Symbol macros are also recognized in contexts
+where
+.meta sym
+denotes a place which is the target of an assignment operation
+like
+.code set
+and similar.
-The replacement <form> is then subject to further expansion, if possible.
-It may be a compound form which is a macro call, or another symbol that
-has a symbol macro binding.
+A
+.code defsymacro
+form is implicitly executed at expansion time, and thus need
+not be wrapped in a
+.code macro-time
+form, just like
+.codn defmacro .
Note: if a symbol macro expands to itself directly, expansion stops. However,
if a symbol macro expands to itself through a chain of expansions,
an infinite expansion time loop results.
-.SS Operator symacrolet
-
-.TP
-Syntax:
-
- (symacrolet ({(<sym> <form>)}*) <body-form>*)
-
-.TP
-Description:
-
-The symacrolet operator binds local, lexically scoped macros that are
-similar to the global symbol macros introduced by defsymacro.
-
-Each <sym> in the bindings list is bound to its corresponding form, creating a
+.coNP Operator @ symacrolet
+.synb
+.mets (symacrolet >> ({( sym << form )}*) << body-form *)
+.syne
+.desc
+The
+.code symacrolet
+operator binds local, lexically scoped macros that are
+similar to the global symbol macros introduced by
+.codn defsymacro .
+
+Each
+.meta sym
+in the bindings list is bound to its corresponding form, creating a
new extension of the expansion-time lexical macro environment.
-Each <body-form> is subsequently macro-expanded in this new environment
+Each
+.meta body-form
+is subsequently macro-expanded in this new environment
in which the new symbol macros are visible.
Note: ordinary lexical bindings such as those introduced by let or by
-function parameters lists shadow symbol macros. If a symbol X is bound
-by both a macrolet and a let, then a body which is enclosed by both
-constructs will see whichever of the two bindings is innermost,
+function parameters lists shadow symbol macros. If a symbol
+.code x
+is bound by nested instances of
+.code macrolet
+and a
+.codn let ,
+then the scope enclosed by both
+constructs will see whichever of the two bindings is more inner,
even though the bindings are active in completely separate phases of
-processing.
-
-.SS Operator tree-bind
-
-.TP
-Syntax:
-
- (tree-bind <macro-style-params> <expr> <form>*)
-
-.TP
-Description:
-
-The tree-bind operator evaluates <expr>, and then uses the
+processing.
+
+.coNP Operator @ tree-bind
+.synb
+.mets (tree-bind < macro-style-params < expr << form *)
+.syne
+.desc
+The
+.code tree-bind
+operator evaluates
+.codn expr ,
+and then uses the
resulting value as a counterpart to a macro-style parameter list.
If the value has a tree structure which matches the parameters,
then those parameters are established as bindings, and the
-<form>-s, if any, are evaluated in the scope of those bindings. The value
-of the last <form> is returned. If there are no forms,
-nil is returned.
-
-Note: this operator throws an exception if there is a mismatch
-between the parameters and the value of <expr>.
-
-.SS Operator tree-case
-
-.TP
-Syntax:
-
- (tree-case <expr> { (<macro-style-params> <form>*) }*)
-
-.TP
-Description:
+.metn form s,
+if any, are evaluated in the scope of those bindings. The value
+of the last
+.meta form
+is returned. If there are no forms,
+.code nil
+is returned.
-The tree case operator evaluates <expr> and matches it against a succession
+Note: this operator throws an exception if there is a
+structural mismatch between the parameters and the value of
+.codn expr .
+
+One way to avoid this exception is to use
+.codn tree-case .
+
+.coNP Operator @ tree-case
+.synb
+.mets (tree-case < expr >> {( macro-style-params << form *)}*)
+.syne
+.desc
+The
+.code tree-case
+operator evaluates
+.meta expr
+and matches it against a succession
of zero or more cases. Each case defines a pattern match, expressed as a macro
-style parameter list <macro-style-params>.
-
-If the object produced by <expr> matches <macro-style-params>, then the
-parameters are bound, becoming local variables, and the <form>-s, if any, are
-evaluated in order in the environment in which those variables are visible.
-
-If there are forms, the value of the last <form> becomes the result value of
-the case, otherwise the result value of the case is nil.
-
-If the result value of a case is the object : (the colon symbol), then
-processing continues with the next case. Otherwise the evaluation of tree-case
+style parameter list
+.metn macro-style-params .
+
+If the object produced by
+.meta expr
+matches
+.metn macro-style-params ,
+then the parameters are bound, becoming local variables, and the
+.metn form s,
+if any, are evaluated in order in the environment in which those variables are
+visible. If there are forms, the value of the last
+.meta form
+becomes the result
+value of the case, otherwise the result value of the case is nil.
+
+If the result value of a case is the object
+.code :
+(the colon symbol), then processing continues with the next case. Otherwise the
+evaluation of
+.code tree-case
terminates, returning the result value.
-If the value of <expr> does not match the <macro-style-params> parameter
-list, then the usual exception is thrown; instead, processing continues
-with the next case.
+If the value of
+.meta expr
+does not match the
+.meta macro-style-params
+parameter list of a case, processing continues with the next case.
-If no cases match, then tree-case terminates, returning nil.
+If no cases match, then
+.code tree-case
+terminates, returning
+.codn nil .
-.SS
-Example:
+.TP* Example:
- ;; reverse function implemented using tree-case
+.cblk
+ ;; reverse function implemented using tree-case
- (defun tb-reverse (obj)
- (tree-case obj
- (() ()) ;; the empty list is just returned
- ((a) obj) ;; one-element list just returned (unnecessary case)
- ((a . b) ^(,*(tb-reverse b) ,a)) ;; car/cdr recursion
- (a a))) ;; atom is just returned
+ (defun tb-reverse (obj)
+ (tree-case obj
+ (() ()) ;; the empty list is just returned
+ ((a) obj) ;; one-element list returned (unnecessary case)
+ ((a . b) ^(,*(tb-reverse b) ,a)) ;; car/cdr recursion
+ (a a))) ;; atom is just returned
+.cble
Note that in this example, the atom case is placed last, because an
argument list which consists of a symbol is a "catch all" match
that matches any object. We know that it matches an atom, because
-the previous (a . b) case matches conses. In general, the order of the cases in
-tree-case is important. Also note that the one-element case can be
-removed.
-
-.SH DEBUGGING FUNCTIONS
-
-.SS Functions source-loc and source-loc-str
-
-.TP
-Syntax:
-
- (source-loc <form>)
- (source-loc-str <form>)
+the previous
+.code (a . b)
+case matches conses. In general, the order of the cases in
+.code tree-case
+is important: even more so than the order of cases in a
+.code cond
+or
+.codn caseql .
+
+.SS* Debugging Functions
+.coNP Functions source-loc and source-loc-str
+.synb
+.mets (source-loc << form )
+.mets (source-loc-str << form )
+.syne
+.desc
+These functions map an expression in a TXR program to the file name and
+line number of the source code where that form came from.
+
+The
+.code source-loc
+function returns the raw information as a cons cell
+whose
+.cod3 car / cdr
+consist of the line number, and file name.
+
+The
+.code source-loc-str
+function formats the information as a string.
-.TP
-Description:
-
-These functions map an expression in a txr program to the file name and
-line number of the source code where that form came from.o
-
-The source-loc function returns the raw information as a cons cell
-whose car/cdr consist of the line number, and file name.
-
-The source-loc-str function formats the information as a string.
-
-If <form> is not a piece of the program source code that was constructed by the
-TXR parser, then source-loc returns nil, and source-loc-str returns a string
-whose text says that source location is not available.
-
-.SS Function rlcp
-
-.TP
-Syntax:
-
- (rlcp <dest-form> <source-form>)
-
-The rlcp function copies the source code location info (rl = read location)
-from the <source-form> object to the <dest-form> object. These objects
+If
+.meta form
+is not a piece of the program source code that was constructed by the
+TXR parser, then
+.code source-loc
+returns
+.codn nil ,
+and
+.code source-loc-str
+returns a string whose text says that source location is not available.
+
+.coNP Function @ rlcp
+.synb
+.mets (rlcp < dest-form << source-form )
+.syne
+.desc
+The
+.code rlcp
+function copies the source code location info ("rl" means "read location")
+from the
+.meta source-form
+object to the
+.meta dest-form
+object. These objects
are pieces of list-based syntax.
Note: the function is intended to be used in macros. If a macro transforms
-<source-form> to <dest-form>, this function can be used to propagate the
+.meta source-form
+to
+.metn dest-form ,
+this function can be used to propagate the
source code location info also, so that when the TXR Lisp evaluator
encounters errors in transformed code, it can give diagnostics which refer
to the original untransformed source code.
-.SH PROFILING
-
-.SS Operator prof
-
-.TP
-Syntax:
-
- (prof <form>*)
-
-.TP
-Description:
-
-The prof operator evaluates the enclosed forms from left to right similarly
-to progn, while determining the memory allocation requests and time
-consumed by the evaluation of the forms.
+.SS* Profiling
+.coNP Operator @ prof
+.synb
+.mets (prof << form *)
+.syne
+.desc
+The
+.code prof
+operator evaluates the enclosed forms from left to right similarly
+to
+.codn progn ,
+while determining the memory allocation requests and time
+consumed by the evaluation of the forms.
If there are no forms, the prof operator measures the smallest measurable
-operation of evaluating nothing and producing nil.
+operation of evaluating nothing and producing
+.codn nil .
If the evaluation terminates normally (not abruptly by a non-local
-control transfer), then prof yields a list consisting of:
-
- (<value> <malloc-bytes> <gc-bytes> <milliseconds>)
-
-where <values> is the value returned by the rightmost <form>, or nil if there
-are no forms, <malloc-bytes> is the total number of bytes of all malloc
+control transfer), then
+.code prof
+yields a list consisting of:
+
+.cblk
+.mets >> ( value < malloc-bytes < gc-bytes << milliseconds )
+.cble
+
+where
+.meta value
+is the value returned by the rightmost
+.metn form ,
+or
+.code nil
+if there are no forms,
+.meta malloc-bytes
+is the total number of bytes of all memroy allocation
requests (or at least those known to the TXR runtime, such as those of all
-internal objects), <gc-bytes> is the total number of bytes drawn from the
-garbage-collected heaps, and <milliseconds> is the total processor time
+internal objects),
+.meta gc-bytes
+is the total number of bytes drawn from the
+garbage-collected heaps, and
+.meta milliseconds
+is the total processor time
consumed over the execution of those forms.
Notes:
-The bytes allocated by the garbage collector from malloc to create
-heap areas are not counted as <malloc-bytes>. <malloc-bytes> includes storage
+The bytes allocated by the garbage collector from the C function
+.code malloc
+to create
+heap areas are not counted as
+.metn malloc-bytes .
+.meta malloc-bytes
+includes storage
such as the space used for dynamic strings, vectors and bignums (in addition to
-their gc-heap allocated nodes), and the various structures used by the cobj
+their gc-heap allocated nodes), and the various structures used by the
+.code cobj
type objects such as streams and hashes. Objects in external libraries that use
-uninstrumented allocators are not counted: for instance the C FILE * streams.
-
-.SS Macro pprof
-
-.TP
-Syntax:
-
- (pprof <form>*)
-
-.TP
-Description:
-
-The pprof (pretty-printing prof) macro is similar to progn. It evaluates forms,
-and returns the rightmost one, or nil if there are no forms.
-
-Over the evaluation of the forms, it counts memory allocations, and measures
-CPU time. If the forms terminate normally, then just prior to returning,
-pprof prints these statistics are printed in a concise report on the
-*std-output* stream, prior to returning the value or nil.
-
-The pprof macro relies on the prof operator.
-
-.SH GARBAGE COLLECTION
-
-.SS Function sys:gc
-
-.TP
-Syntax:
+uninstrumented allocators are not counted: for instance the C
+.code FILE *
+streams.
+
+.coNP Macro @ pprof
+.synb
+.mets (pprof << form *)
+.syne
+.desc
+The
+.code pprof
+(pretty-printing
+.codn prof )
+macro is similar to
+.codn progn .
+It evaluates
+.metn form s,
+and returns the rightmost one, or
+.code nil
+if there are no forms.
+
+Over the evaluation of
+.metn form s,
+it counts memory allocations, and measures
+CPU time. If
+.metn form s
+terminate normally, then just prior to returning,
+.code pprof
+prints these statistics in a concise report on the
+.codn *std-output* .
+
+The
+.code pprof
+macro relies on the
+.code prof
+operator.
+.SS* Garbage Collection
+.coNP Function @ sys:gc
+.synb
(sys:gc)
-
-.TP
-Description:
-
-The gc function triggers garbage collection. Garbage collection means
+.syne
+.desc
+The
+.code gc
+function triggers garbage collection. Garbage collection means
that unreachable objects are identified and reclaimed, so that their
storage can be re-used.
-.SS Function sys:gc-set-delta
-
-.TP
-Syntax:
-
- (sys:gc-set-delta <bytes>)
-
-.TP
-Description:
-
-The gc-set-delta function sets the GC delta parameter.
+.coNP Function @ sys:gc-set-delta
+.synb
+.mets (sys:gc-set-delta << bytes )
+.syne
+.desc
+The
+.code gc-set-delta
+function sets the GC delta parameter.
Note: This function may disappear in a future release of TXR or suffer
a backward-incompatible change in its syntax or behavior.
@@ -15986,24 +24677,29 @@ of memory. It is for this reason that the garbage collector uses the GC delta.
There is a default GC delta of 64 megabytes. This may be overridden in
special builds of TXR for small systems.
-.SH MODULARIZATION
-
-.SS Special variable *self-path*
-
+.SS* Modularization
+.coNP Special variable @ *self-path*
+.desc
This variable holds the invocation path name of the TXR program.
-.SH DEBUGGER
-
+.SS* Debugger
.B TXR
has a simple, crude, built-in debugger. The debugger is invoked by adding
-the -d command line option to an invocation of txr.
+the
+.code -d
+command line option to an invocation of txr.
In this debugger it is possible to step through code, set breakpoints,
and examine the variable binding environment.
-Prior to executing any code, the debugger waits at the txr> prompt,
-allowing for the opportunity to set breakpoints.
+Prior to executing any code, the debugger waits at the
+.code txr>
+prompt, allowing for the opportunity to set breakpoints.
-Help can be obtained with the h or ? command.
+Help can be obtained with the
+.code h
+or
+.code ?
+command.
Whenever the program stops at the debugger, it prints the Lisp-ified
piece of syntax tree that is about to be interpreted.
@@ -16011,11 +24707,17 @@ It also shows the context of the input being matched.
The s command can be used to step into a form; n to step over.
Sometimes the behavior seems counter-intuitive. For instance stepping
-over a @(next) directive actually means skipping everything which follows
-it. This is because the query material after a @(next) is actually child
-nodes in the abstract syntax tree node of the next directive.
-
-.SS Sample Session
+over a
+.code @(next)
+directive actually means skipping everything which follows
+it. This is because the query material after a
+.code @(next)
+is actually child
+nodes in the abstract syntax tree node of the
+.code next
+directive, whereas the surface syntax appears flat.
+
+.coNP Sample Session
Here is an example of the debugger being applied to a web scraping program
which connects to a US NAVY clock server to retrieve a dynamically-generated
@@ -16024,6 +24726,7 @@ The handling of the web request is done by the wget command; the txr
query opens a wget command as and scans the body of the HTTP response containing
HTML. This is the code, saved in a file called navytime.txr:
+.cblk
@(next `!wget -c http://tycho.usno.navy.mil/cgi-bin/timer.pl -O - 2> /dev/null`)
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final"//EN>
<html>
@@ -16043,18 +24746,26 @@ HTML. This is the code, saved in a file called navytime.txr:
@MO-@DD @HH:@MM:@SS @PM @TZ
@ (end)
@(end)
+.cble
This is the debug session:
+.cblk
$ txr -d navytime.txr
stopped at line 1 of navytime.txr
form: (next (sys:quasi "!wget -c http://tycho.usno.navy.mil/cgi-bin/timer.pl -O - 2> /dev/null"))
depth: 1
data (nil):
nil
+.cble
-The user types s to step into the (next ...) form.
+The user types
+.code s
+to step into the
+.code (next ...)
+form.
+.cblk
txr> s
stopped at line 2 of navytime.txr
form: (sys:text "<!DOCTYPE" (#<sys:regex: 95e4590> 1+ #\espace) "HTML" (#<sys:regex: 95e4618> 1+ #\espace) "PUBLIC" (#<sys:regex: 95e46a8> 1+ #\espace) "\e"-//W3C//DTD" (#<sys:regex: 95e4750> 1+ #\espace) "HTML" (#<sys:regex: 95e47d8> 1+ #\espace) "3.2" (#<sys:regex: 95e4860> 1+ #\espace) "Final\e"//EN>")
@@ -16062,61 +24773,82 @@ The user types s to step into the (next ...) form.
data (1):
"<!DOCTYPE HTML PUBLIC \e"-//W3C//DTD HTML 3.2 Final\e"//EN>"
txr> s
+.cble
-The current form now is a sys:text form which is an internal representation of
+The current form now is a
+.code sys:text
+form which is an internal representation of
a block of horizontal material. The pattern matching is in vertical mode at
this point, and so the line of data is printed without an indication of
-character position.
+character position.
+.cblk
stopped at line 2 of navytime.txr
form: (sys:text "<!DOCTYPE" (#<sys:regex: 95e4590> 1+ #\espace) "HTML" (#<sys:regex: 95e4618> 1+ #\espace) "PUBLIC" (#<sys:regex: 95e46a8> 1+ #\espace) "\e"-//W3C//DTD" (#<sys:regex: 95e4750> 1+ #\espace) "HTML" (#<sys:regex: 95e47d8> 1+ #\espace) "3.2" (#<sys:regex: 95e4860> 1+ #\espace) "Final\e"//EN>")
depth: 3
data (1:0):
"" . "<!DOCTYPE HTML PUBLIC \e"-//W3C//DTD HTML 3.2 Final\e"//EN>"
+.cble
-The user types s to step in.
+The user types
+.code s
+to step in.
+.cblk
txr> s
stopped at line 2 of navytime.txr
form: "<!DOCTYPE"
depth: 4
data (1:0):
"" . "<!DOCTYPE HTML PUBLIC \e"-//W3C//DTD HTML 3.2 Final\e"//EN>"
+.cble
-Now, the form about to be processed is the first item of the (sys:text ...),
-a the string "<!DOCTYPE".
+Now, the form about to be processed is the first item of the
+.codn (sys:text ...) ,
+the string
+.strn <!DOCTYPE .
The input is shown broken into two quoted strings with a dot in between.
The dot indicates the current position. The left string is empty, meaning
that this is the leftmost position. The programmer steps:
+.cblk
txr> s
stopped at line 2 of navytime.txr
form: (#<sys:regex: 95e4590> 1+ #\espace)
depth: 4
data (1:9):
"<!DOCTYPE" . " HTML PUBLIC \e"-//W3C//DTD HTML 3.2 Final\e"//EN>"
+.cble
-Control has now passed to the second element of the (sys:text ...),
+Control has now passed to the second element of the
+.codn (sys:text ...) ,
a regular expression which matches one or more spaces, generated by
a single space in the source code according to the language rules.
-The input context shows that "<!DOCTYPE" was matched in the input, and the
-position moved past it.
+The input context shows that
+.str <!DOCTYPE
+was matched in the input, and the position moved past it.
+.cblk
txr> s
stopped at line 2 of navytime.txr
form: "HTML"
depth: 4
data (1:10):
"<!DOCTYPE " . "HTML PUBLIC \e"-//W3C//DTD HTML 3.2 Final\e"//EN>"
+.cble
Now, the regular expression has matched and moved the position past
-the space; the facing input is now "HTML ...".
+the space; the facing input is now
+.strn "HTML ..." .
-The programmer then repeats the s command by hitting Enter.
+The programmer then repeats the
+.code s
+command by hitting Enter.
- txr>
+.cblk
+ txr>
stopped at line 2 of navytime.txr
form: (#<sys:regex: 95e4618> 1+ #\espace)
depth: 4
@@ -16146,15 +24878,20 @@ The programmer then repeats the s command by hitting Enter.
depth: 4
data (1:34):
"<!DOCTYPE HTML PUBLIC \e"-//W3C//DTD" . " HTML 3.2 Final\e"//EN>"
+.cble
It is not evident from the session transcript, but during interactive use,
the input context appears to be animated. Whenever the programmer hits
Enter, the new context is printed and the dot appears to advance.
Eventually the programmer becomes bored and place a breakpoint on line 15,
-where the @(output) block begins, and invokes the c command to continue the
-execution:
+where the
+.code @(output)
+block begins, and invokes the
+.code c
+command to continue the execution:
+.cblk
txr> b 15
txr> c
stopped at line 15 of navytime.txr
@@ -16162,16 +24899,24 @@ execution:
depth: 2
data (16):
""
+.cble
-The programmer issues a v command to take a look at the variable bindings,
-which indicate that the @(collect) has produced some lists.
+The programmer issues a
+.code v
+command to take a look at the variable bindings,
+which indicate that the
+.code @(collect)
+has produced some lists:
+.cblk
txr> v
bindings:
0: ((PM " " "PM" "PM" "PM" "PM" "PM" "PM") (TZNAME "Universal Time" "Eastern Time" "Central Time" "Mountain Time" "Pacific Time" "Alaska Time" "Hawaii-Aleutian Time") (TZ "UTC" "EDT" "CDT" "MDT" "PDT" "AKDT" "HAST") (SS "35" "35" "35" "35" "35" "35" "35") (MM "32" "32" "32" "32" "32" "32" "32") (HH "23" "07" "06" "05" "04" "03" "01") (DD "30" "30" "30" "30" "30" "30" "30") (MO "Mar" "Mar" "Mar" "Mar" "Mar" "Mar" "Mar"))
+.cble
Then a continue command, which finishes the program, whose output appears:
+.cblk
txr> c
Mar-30 23:22:52 UTC
Mar-30 07:22:52 PM EDT
@@ -16180,8 +24925,9 @@ Then a continue command, which finishes the program, whose output appears:
Mar-30 04:22:52 PM PDT
Mar-30 03:22:52 PM AKDT
Mar-30 01:22:52 PM HAST
+.cble
-.SH COMPATIBILITY
+.SS* Compatibility
New TXR versions are usually intended to be backward-compatible with prior
releases in the sense that documented features will continue to work in
@@ -16192,63 +24938,116 @@ differently in a new version, replacing an error situation with functionality
is usually not considered a deviation from backward-compatibility.
When a change is introduced which is not backward compatible, TXR's
--C option can be used to request emulation of old behavior.
+.code -C
+option can be used to request emulation of old behavior.
The option was introduced in TXR 98, and so the oldest TXR version which
can be emulated is TXR 97.
-Here are values which have a special meaning as arguments to -C:
-the -C option, along with a description of what behaviors are affected:
-
+Here are values which have a special meaning as arguments to the
+.code -C
+option, along with a description of what behaviors are affected:
.IP 97
-Up to TXR 97, the error exception symbols such as "file-error" were named with
-underscores, as in "file-error". These error symbols existed: type_error,
-internal_error, numeric_error, range_error, query_error, file_error and
-process_error.
-
-.SH APPENDIX A: NOTES ON EXOTIC REGULAR EXPRESSIONS
-
+Up to TXR 97, the error exception symbols such as
+.code file-error
+were named with underscores, as in
+.codn file_error .
+These error symbols existed:
+.codn type_error ,
+.codn internal_error ,
+.codn numeric_error ,
+.codn range_error ,
+.codn query_error ,
+.code file_error
+and
+.codn process_error .
+
+.SH* Appendix
+.SS* A. NOTES ON EXOTIC REGULAR EXPRESSIONS
Users familiar with regular expressions may not be familiar with the complement
and intersection operators, which are often absent from text processing tools
that support regular expressions. The following remarks are offered in hope
that they are of some use.
-.SS Equivalence to Sets
-
+.TP* "Equivalence to Sets"
Regexp intersection is not essential; it may be obtained from complement and
union as follows, since De Morgan's law applies to regular expression algebra:
-(R1)&(R2) = ~(~(R1)|~(R2)). (The complement of the union of the complements of
+.code (R1)&(R2)
+=
+.codn ~(~(R1)|~(R2)) .
+(The complement of the union of the complements of
R1 and R2 constitutes the intersection.) This law works because the regular
expression operators denote set operations in a straightforward way. A regular
expression denotes a set of strings (a potentially infinite one) in a condensed
-way. The union of two regular expressions R1 | R2 denotes the union of the set
-of texts denoted by R1 and that denoted by R2. Similarly R1 & R2 denotes a set
-intersection, and ~R denotes a set complement. Thus algebraic laws
+way. The union of two regular expressions
+.code R1|R2
+denotes the union of the set
+of texts denoted by
+.code R1
+and that denoted by
+.codn R2 .
+Similarly
+.code R1&R2
+denotes a set intersection, and
+.code ~R
+denotes a set complement. Thus algebraic laws
that apply to set operations apply to regular expressions. It's useful to keep
in mind this relationship between regular expressions and sets in understanding
intersection and complement.
-Given a finite set of strings, like the set { "abc", "def" }, which corresponds
-to the regular expression (abc|def), the complement is the set which contains
-an infinite number of strings: it consists of all possible strings except "abc"
-and "def". It includes the empty string, all strings of length 1, all strings
-of length 2, all strings of length 3 other than "abc" and "def", all strings of
-length 4, etc. This means that a "harmless looking" expression like ~(abc|def)
+Given a finite set of strings, like the set
+.cblk
+{ "abc", "def" }
+.cble
+which corresponds to the regular expression
+.codn (abc|def) ,
+the complement is the set which contains
+an infinite number of strings: it consists of all possible strings except
+.str abc
+and
+.strn def .
+It includes the empty string, all strings of length 1, all strings
+of length 2, all strings of length 3 other than
+.str abc
+and
+.strn def ,
+all strings of
+length 4, etc. This means that a "harmless looking" expression like
+.code ~(abc|def)
can actually match arbitrarily long inputs.
-.SS Set Difference
-
-How about matching only three-character-long strings other than "abc" or "def"?
+.TP* "Set Difference"
+How about matching only three-character-long strings other than
+.str abc
+or
+.strn def ?
To express this, regex intersection can be used: these strings are the
intersection of the set of all three-character strings, and the set of all
-strings which are not "abc" or "def". The straightforward set-based reasoning
-leads us to this: ...&~(abc|def). This A&~B idiom is also called set
-difference, sometimes notated with a minus sign: A-B (which is not
-supported in
+strings which are not
+.str abc
+or
+.strn def .
+The straightforward set-based reasoning
+leads us to this:
+.codn ...&~(abc|def) .
+This
+.code A&~B
+idiom is also called set
+difference, sometimes notated with a minus sign:
+.code A-B
+(which is not supported in
.B TXR
-regular expression syntax). Elements which are in the set A, but not B, are
-those elements which are in the intersection of A with the complement of B.
-This is similar to the arithmetic rule A - B = A + -B: subtraction is
+regular expression syntax). Elements which are in the set
+.codn A ,
+but not
+.codn B ,
+are those elements which are in the intersection of
+.code A
+with the complement of
+.codn B .
+This is similar to the arithmetic rule
+.codn A - B = A + -B :
+subtraction is
equivalent to addition of the additive inverse. Set difference is a useful
tool: it enables us to write a positive match which captures a more general set
than what is intended (but one whose regular expression is far simpler
@@ -16256,7 +25055,7 @@ than a positive match for the exact set we want), then we can
intersect this over-generalized set with the complemented set of
another regular expression which matches the particulars that we wish excluded.
-.SS Expressivity versus Power
+.TP* "Expressivity versus Power"
It turns out that regular expressions which do not make use of the
complement or intersection operators are just as powerful as expressions
@@ -16274,49 +25073,97 @@ complement and intersection leads to natural ways of expressing many kinds of
matching sets, which not only demonstrate the power to carry out an operation,
but also easily express the concept.
-.SS Example: Matching C Language Comments
+.TP* "Example: Matching C Language Comments"
For instance, using complement, we can write a straightforward regular
expression which matches C language comments. A C language
-comment is the digraph /*, followed by any string which does not contain the
-closing sequence */, followed by that closing sequence.
-Examples of valid comments are /**/, /* abc */ or /***/. But C
+comment is the digraph
+.codn /* ,
+followed by any string which does not contain the
+closing sequence
+.codn */ ,
+followed by that closing sequence.
+Examples of valid comments are
+.codn /**/ ,
+.code /* abc */
+or
+.codn /***/ .
+But C
comments do not nest (cannot contain comments), so that
-/* /* nested */ */ actually consists of the comment /* /* nested */,
-which is followed by the trailing junk */.
+.code /* /* nested */ */
+actually consists of the comment
+.codn /* /* nested */ ,
+which is followed by the trailing junk
+.codn */ .
Our simple characterization of interior part of a C comment as a string
which does not contain the terminating digraph makes use of the
complement, and can be expressed using the complemented regular expression like
-this: (~.*[*][/].*). That is to say, strings which contain */ are matched by
-the expression .*[*][/].*: zero or more arbitrary characters, followed by
-*/, followed by zero or more arbitrary characters. Therefore, the complement of
-this expression matches all other strings: those which do not contain */.
-These strings up the inside of a C comment between the /* and */.
+this:
+.codn (~.*[*][/].*) .
+That is to say, strings which contain
+.code */
+are matched by
+the expression
+.codn .*[*][/].* :
+zero or more arbitrary characters, followed by
+.codn */ ,
+followed by zero or more arbitrary characters. Therefore, the complement of
+this expression matches all other strings: those which do not contain
+.codn */ .
+These strings make up the inside of a C comment between the
+.code /*
+and
+.codn */ .
The equivalent simple regex is quite a bit more complicated.
Without complement, we must somehow write a positive match for all strings such
-that we avoid matching */. Obviously, sequences of characters other than *
-are included: [^*]*. Occurrences of * are also allowed, but only if followed
+that we avoid matching
+.codn */ .
+Obviously, sequences of characters other than
+.code *
+are included:
+.codn [^*]* .
+Occurrences of
+.code *
+are also allowed, but only if followed
by something other than a slash, so let's include this via union:
- ([^*]|[*][^/])*.
+.cblk
+ ([^*]|[*][^/])*.
+.cble
Alas, already, we have a bug in this expression. The
-subexpression [*][^/] can match "**", since a * is not a /. If the next
-character in the input is /, we missed a comment close. To fix the problem we
-revise to this:
-
+subexpression
+.code [*][^/]
+can match
+.codn ** ,
+since a
+.code *
+is not a
+.codn / .
+If the next character in the input is
+.codn / ,
+we missed a comment close. To fix the problem we
+revise to this:
+
+.cblk
([^*]|[*][^*/])*
+.cble
(The interior of a C language comment is a any
mixture of zero or more non-asterisks, or digraphs consisting of an asterisk
followed by something other than a slash or another asterisk). Oops, now we
have a problem again. What if two asterisks occur in a comment? They are not
-matched by [^*], and they are not matched by [*][^*/]. Actually, our regex must
-not simply match asterisk-non-asterisk digraphs, but rather sequences of one or
-more asterisks followed by a non-asterisk:
-
+matched by
+.codn [^*] ,
+and they are not matched by
+.codn [*][^*/] .
+Actually, our regex must not simply match asterisk-non-asterisk digraphs, but
+rather sequences of one or more asterisks followed by a non-asterisk:
+
+.cblk
([^*]|[*]*[^*/])*
+.cble
This is still not right, because, for instance, it fails to match the interior
of a comment which is terminated by asterisks, including the simple test cases
@@ -16324,20 +25171,30 @@ where the comment interior is nothing but asterisks. We have no provision in
our expression for this case; the expression requires all runs of asterisks to
be followed by something which is not a slash or asterisk. The way to fix this
is to add on a subexpression which optionally matches a run of zero or more
-interior asterisks before the comment close:
+interior asterisks before the comment close:
+.cblk
([^*]|[*]*[^*/])*[*]*
+.cble
Thus our the semi-final regular expression is
+.cblk
[/][*]([^*]|[*]*[^*/])*[*]*[*][/]
+.cble
-(A C comment is an interior string enclosed in /* */, where this interior part
+(Interpretation: a C comment is an interior string enclosed in
+.codn /* */ ,
+where this interior part
consists of a mixture of non-asterisk characters, as well as runs of asterisk
characters which are terminated by a character other than a slash, except for
possibly one rightmost run of asterisks which extends to the end of the
interior, touching the comment close. Phew!) One final simplification is
-possible: the tail part [*]*[*][/] can be reduced to [*]+[/] such that the
+possible: the tail part
+.code [*]*[*][/]
+can be reduced to
+.code [*]+[/]
+such that the
final run of asterisks is regarded as part of an extended comment terminator
which consists of one or more asterisks followed by a slash. The regular
expression works, but it's cryptic; to someone who has not developed it, it
@@ -16348,34 +25205,76 @@ trial-and-error development involving numerous test cases, resulting in an
expression that doesn't have a straightforward relationship to the original
idea.
-.SS The Non-Greedy Operator
+.TP* "The Non-Greedy Operator"
-The non-greedy operator % is actually defined in terms of a set difference,
+The non-greedy operator
+.code %
+is actually defined in terms of a set difference,
which is in turn based on intersection and complement. The uninteresting case
-(R%) where the right operand is empty reduces to (R*): if there is no trailing
-context, the non-greedy operator matches R as far as possible, possibly to the
-end of the input, exactly like the greedy Kleene. The interesting case (R%T)
-is defined as a "syntactic sugar" for the equivalent expression
-((R*)&(~.*(T&.+).*))T which means: match the longest string which is matched
-by R*, but which does not contain a non-empty match for T; then, match T. This
-is a useful and expressive notation. With it, we can write the regular
-expression for matching C language comments simply like this: [/][*].%[*][/]
-(match the opening sequence /*, then match a sequence of zero or more
-characters non-greedily, and then the closing sequence */. With the non-greedy
+.code (R%)
+where the right operand is empty reduces to
+.codn (R*) :
+if there is no trailing
+context, the non-greedy operator matches
+.code R
+as far as possible, possibly to the
+end of the input, exactly like the greedy operator. The interesting case
+.code (R%T)
+is defined as a "syntactic sugar" which expands to the expression
+.code ((R*)&(~.*(T&.+).*))T
+which means: match the longest string which is matched
+by
+.codn R* ,
+but which does not contain a non-empty match for
+.codn T ;
+then, match
+.codn T .
+This is a useful and expressive notation. With it, we can write the regular
+expression for matching C language comments simply like this:
+.code [/][*].%[*][/]
+(match the opening sequence
+.codn /* ,
+then match a sequence of zero or more
+characters non-greedily, and then the closing sequence
+.codn */ .
+With the non-greedy
operator, we don't have to think about the interior of the comment as set of
-strings which excludes */. Though the non-greedy operator appears expressive,
+strings which excludes
+.codn */ .
+Though the non-greedy operator appears expressive,
its apparent simplicity may be deceptive. It looks as if it works "magically"
-by itself; "somehow" this .% "knows" only to consume enough characters so that
+by itself; "somehow" this
+.code .%
+part "knows" only to consume enough characters so that
it doesn't swallow an occurrence of the trailing context. Care must be taken
that the trailing context passed to the operator really is the correct text
that should be excluded by the non-greedy match. For instance, take the
-expression .%abc. If you intend the trailing context to be merely a, you must
-be careful to write (.%a)bc. Otherwise the trailing context is abc, and this
-means that the .% match will consume the longest string that does not contain
-"abc", when in fact what was intended was to consume the longest string that
-does not contain a. The change in behavior of the % operator upon modifying the
+expression
+.codn .%abc .
+If you intend the trailing context to be merely
+.codn a ,
+you must be careful to write
+.codn (.%a)bc .
+Otherwise, the trailing context is
+.codn abc ,
+and this means that the
+.code .%
+match will consume the longest string that does not contain
+.codn abc ,
+when in fact what was intended was to consume the longest string that
+does not contain
+.codn a .
+The change in behavior of the
+.code %
+operator upon modifying the
trailing context is not as intuitive as that of the * operator, because the
-trailing context is deeply involved in its logic. For single-character
-trailing contexts, it may be a good idea to use a complemented character class
-instead. That is to say, rather than (.%a)bc, consider [^a]*abc. The set of
-strings which don't contain the character a is adequately expressed by [^a]*.
+trailing context is deeply involved in its logic.
+
+On a related note, for single-character trailing contexts, it may be a good
+idea to use a complemented character class instead. That is to say, rather than
+.codn (.%a)bc ,
+consider
+.codn [^a]*abc .
+The set of strings which don't contain the
+character a is adequately expressed by
+.codn [^a]* .