stk/Doc/Reference/Reference2.tex

1789 lines
59 KiB
TeX

%
% STk Reference manual (Part 2)
%
% Author: Erick Gallesio [eg@unice.fr]
% Creation date: ??-Nov-1993 ??:??
% Last file update: 23-Jul-1996 08:59
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%
%%%% Section 6.11 Keywords
%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{Keywords}
\label{keywords}
Keywords are symbolic constants which evaluate to themselves. A keyword must
begin with a colon.
\begin{entry}{%
\proto{keyword?}{ obj}{procedure}}
\saut
Returns {\schtrue} if \var{obj} is a keyword, otherwise returns {\schfalse}.
\end{entry}
\begin{entry}{%
\proto{make-keyword}{ obj}{procedure}}
\saut
Builds a keyword from the given \var{obj}. \var{obj} must be a symbol
or a string. A colon is automatically prepended.
\begin{scheme}
(make-keyword "test") \lev :test
(make-keyword 'test) \lev :test
(make-keyword ":hello") \lev ::hello
\end{scheme}
\end{entry}
\begin{entry}{%
\proto{keyword->string}{ keyword}{procedure}}
\saut
Returns the name of \var{keyword} as a string. The leading colon is
included in the result. %% axe: why this asymmetry ?
\begin{scheme}
(keyword->string :test) \lev ":test"
\end{scheme}
\end{entry}
%% axe: added description of list's format. (proposals for better
%% phrasing are welcome)
\begin{entry}{%
\proto{get-keyword}{ keyword list}{procedure}
\proto{get-keyword}{ keyword list default}{procedure}}
\saut
\var{List} must be a list of keywords and their respective values.
\ide{Get-keyword} scans the \var{list} and returns the value
associated with the given \var{keyword}. If the \var{keyword} does
not appear in an odd position in \var{list}, the specified
\var{default} is returned, or an error is raised if no default was
specified.
\begin{scheme}
(get-keyword :one '(:one 1 :two 2)) \lev 1
(get-keyword :four '(:one 1 :two 2) \schfalse) \lev \schfalse
(get-keyword :four '(:one 1 :two 2)) \lev \scherror
\end{scheme}
\end{entry}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%
%%%% Section 6.12: Tk commands
%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{Tk commands}
\label{tkcommand}
As we mentioned in the introduction, {\stk} can easily communicate
with the Tk toolkit\index{Tk toolkit}\index{toolkit}. All the commands
defined by the Tk toolkit are visible as \ide{Tk-command}s, a basic
type recognized by the interpreter. \ide{Tk-command}s can be called
like regular scheme procedures, serving as an entry point into the Tk
library.
%
\vskip3mm
\begin{note}
Some \ide{Tk-command}s can dynamically create other
\ide{Tk-command}s. For instance, execution of the expression
\begin{scheme}
(label '.lab)
\end{scheme} %
will create a new \ide{Tk-command} called ``\var{.lab}''. This new
object, which was created by a primitive \ide{Tk-command}, will be
called a \var{widget}\index{widget}.
\end{note}
\begin{note}
When a new widget is created, it captures its creation environment. This
permits to have bindings which access variables in the scope of the widget
creation call (see \ref{addresses}). %% ??
\end{note}
\begin{entry}{%
\proto{tk-command?}{ obj}{procedure}}
\saut
Returns {\schtrue} if \var{obj} is a \ide{Tk-command}, otherwise
returns {\schfalse}.
\begin{scheme}
(tk-command? label) \lev {\schtrue}
(begin (label '.lab) (tk-command? .lab)) \lev {\schtrue}
(tk-command? 12) \lev {\schfalse}
\end{scheme}
\end{entry}
\begin{entry}{%
\proto{widget?}{ obj}{procedure}}
\saut
Returns {\schtrue} if \var{obj} is a widget, otherwise returns
{\schfalse}. A widget is a \ide{Tk-command} created by a primitive
\ide{Tk-command} such as \ide{button}, \ide{label}, \ide{menu}, etc.
\begin{scheme}
(widget? label) \lev {\schfalse}
(begin (label '.lab) (widget? .lab)) \lev {\schtrue}
(widget? 12) \lev {\schfalse}
\end{scheme}
\end{entry}
\begin{entry}{%
\proto{widget->string}{ widget}{procedure}}
\saut
Returns the widget name of \var{widget} as a string.
\begin{scheme}
(begin (label '.lab) (widget->string .lab)) \lev ".lab"
\end{scheme}
\end{entry}
\begin{entry}{%
\proto{string->widget}{ str}{procedure}}
\saut
Returns the widget whose name is \var{str} if it exists; otherwise
returns {\schfalse}.
\begin{scheme}
(begin (label '.lab) (string->widget ".lab")) \lev the \ide{Tk-command} named ".lab"
\end{scheme}
\end{entry}
\begin{entry}{%
\proto{widget-name}{ widget}{procedure}}
\saut
Returns the widget name of \var{widget} as a symbol.
\begin{scheme}
(begin (label '.lab) (widget->name .lab)) \lev .lab
\end{scheme}
\end{entry}
\begin{entry}{
\proto{set-widget-data!}{ widget expr}{procedure}}
\saut
%
\ide{Set-widget-data!} associates arbitrary data with a \var{widget}.
The system makes no assumptions about the type of {\tt expr}; the data
is for programmer convenience only. As shown below, it could be used
as a kind of property list for widgets.
\end{entry}
\begin{entry}{
\proto{get-widget-data}{ widget}{procedure}}
\saut
Returns the data previously associated with \var{widget} if it exists;
otherwise returns {\schfalse}.
\begin{scheme}
(begin
(set-widget-data! .w '(:mapped {\schtrue} :geometry "10x50"))
(get-keyword :mapped (get-widget-data .w))) \lev {\schtrue}
\end{scheme}
\end{entry}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%
%%%% Section 6.13: Environments
%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{Environments}
\label{environment}
Environments are first class objects in STk. The following primitives
are defined on environments.
\begin{entry}{%
\proto{environment?}{ obj} {procedure}}
\saut
Returns {\schtrue} if \var{obj} is an environment, otherwise returns
{\schfalse}.
\end{entry}
\begin{entry}{%
\proto{the-environment} {} {procedure}}
\saut
Returns the current environment.
\end{entry}
\begin{entry}{%
\proto{global-environment} {} {procedure}}
\saut
Returns the ``global'' environment (i.e. the toplevel environment).
\mainindex{top level environment}
\end{entry}
\begin{entry}{%
\proto{parent-environment} { env} {procedure}}
\saut
Returns the parent environment of \var{env}. If env is the ``global''
environment (i.e. the toplevel environment), \ide{parent-environment}
returns {\schfalse}.
\end{entry}
\begin{entry}{%
\proto{environment->list}{ environment} {procedure}}
\saut
Returns a list of {\em a-lists}, representing the bindings in
\var{environment}. Each {\em a-list} describes one level of bindings,
with the innermost level coming first.
\begin{scheme}
(define E (let ((a 1) (b 2))
(let ((c 3))
(the-environment))))
(car (environment->list E)) \ev ((c . 3))
(cadr (environment->list E)) \ev ((b . 2) (a . 1))
\end{scheme}
\end{entry}
\begin{entry}{%
\proto{procedure-environment}{ procedure} {procedure}}
\saut
Returns the environment associated with \var{procedure}.
\ide{Procedure-environment} returns {\schfalse} if \var{procedure}
is not a closure.
\begin{scheme}
(define foo (let ((a 1)) (lambda () a)))
(car (environment->list
(procedure-environment foo)))
\ev ((a . 1))
\end{scheme}
\end{entry}
\begin{entry}{%
\proto{symbol-bound?}{ symbol}{procedure}
\proto{symbol-bound?}{ symbol environment}{procedure}}
\saut
Returns {\schtrue} if \var{symbol} has a value in the given
\var{environment}, otherwise returns {\schfalse}. \var{Environment}
may be omitted, in which case it defaults to the global environment.
\end{entry}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%
%%%% Section 6.14: Macros
%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{Macros}
\label{macros}
{\stk} provides low level macros.
\begin{note}
{\stk} macros are not the sort of macros defined in the appendix of {\rrrr},
but rather the macros one can find in most of Lisp dialects.
\end{note}
\begin{entry}{%
\proto{macro}{ \hyper{formals} \hyper{body}}{\exprtype}}
\saut
{\tt Macro} permits to create a macro. When a macro is called, the whole form
(i.e. the macro itself and its parameters) is passed to the macro body.
Binding association is done in the environment of the call. The result of the
binding association is called the {\em macro-expansion}\index{macro-expansion}.
The result of the macro call is the result of the evaluation of the
macro expansion in the call environment.
%% FIXME: This needs rephrasing...
\begin{scheme}
(define foo (macro f `(quote ,f)))
(foo 1 2 3) \ev (foo 1 2 3)
(define 1+ (macro form (list + (cadr form) 1)))
(let ((x 1)) (1+ x)) \ev 2
\end{scheme}
\end{entry}
\begin{entry}{%
\proto{macro?}{ obj}{procedure}}
\saut
Returns {\schtrue} if \var{obj} is a macro, otherwise returns {\schfalse}.
\end{entry}
\begin{entry}{%
\proto{macro-expand-1}{ form}{procedure}
\proto{macro-expand}{ form}{procedure}}
\saut
\ide{Macro-expand-1} returns the macro expansion of \var{form} if
it is a macro call, otherwise \var{form} is returned unchanged.
\ide{Macro-expand} is similar to \ide{macro-expand-1}, but repeately
expand \var{form} until it is no longer a macro call.
\begin{scheme}
(define 1- (macro form `(- ,(cadr form) 1)))
(define -- (macro form `(1- ,(cadr form))))
(macro-expand-1 '(1- 10)) \ev (- 10 1)
(macro-expand '(1- 10)) \ev (- 10 1)
(macro-expand-1 '(-- 10)) \ev (1- 10)
(macro-expand '(-- 10)) \ev (- 10 1)
\end{scheme}
\end{entry}
\begin{entry}{%
\proto{macro-expand}{ form}{procedure}}
\saut
Returns the macro expansion of \var{form} if it is a macro call, otherwise
\var{form} is returned unchanged. Macro expansion continue until, the form
obtained is
\begin{scheme}
(define 1- (macro form (list '- (cadr form) 1)))
(macro-expand '(1- 10)) \ev (- 10 1)
\end{scheme}
\end{entry}
\begin{entry}{%
\proto{macro-body}{ macro}{procedure}}
\saut
Returns the body of \var{macro}
\begin{scheme}
(macro-body 1+)
\ev (macro form (list + (cadr form) 1))
\end{scheme}
\end{entry}
\begin{entry}{%
\proto{define-macro}{ (\hyper{name} \hyper{formals}) \hyper{body}}{macro}}
\saut
\ide{Define-macro} is a macro which permits to define a macro more easily than
with the \ide{macro} form. It is similar to the {\tt defmacro} of Common
Lisp~\cite{CLtL2}.
\begin{scheme}
(define-macro (incr x) `(set! ,x (+ ,x 1)))
(let ((a 1)) (incr a) a) \ev 2
(define-macro (when test . body)
`(if ,test ,@(if (null? (cdr body)) body `((begin ,@body)))))
(macro-expand '(when a b)) \ev (if a b)
(macro-expand '(when a b c d))
\ev (if a (begin b c d))
\end{scheme}
\begin{note}
Calls to macros defined by \ide{define-macro} are physically replaced by their
macro-expansion if the variable \ide{*debug*} is {\schfalse} (i.e. their body
is ``in-lined'' in the macro call). To avoid this
feature, and to ease debugging, you have to set this variable to {\schtrue}.
(See also \ref{uncode}).
\end{note}
\end{entry}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%
%%%% Section 6.15: System procedures
%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{System procedures}
This section lists a set of procedures which permits to access some system
internals.
\begin{entry}{%
\proto{expand-file-name}{ string} {procedure}}
\saut
\ide{Expand-file-name} expands the filename given in \var{string} to
an absolute path. This function understands the {\em tilde
convention}\index{tilde expansion} for filenames.
\begin{scheme}
;; Current directory is /users/eg/STk
(expand-file-name "..") \lev "/users/eg"
(expand-file-name "{\tilda}root/bin) \lev "/bin"
(expand-file-name "{\tilda}/STk)" \lev "/users/eg/STk"
\end{scheme}
\end{entry}
\begin{entry}{%
\proto{canonical-path}{ path} {procedure}}
\saut
Expands all symbolic links in \var{path} and returns its canonicalized
absolute pathname. The resulting path do not have symbolic links. If
\var{path} doesn't designate a valid pathname, \var{canonical-path} returns
\schfalse.
\end{entry}
\begin{entry}{%
\proto{dirname}{ string} {procedure}}
\saut
Returns a string containing all but the last component of the path name given in
\var{string}.
\begin{scheme}
(dirname "/a/b/c.stk") \lev "/a/b"
\end{scheme}
\end{entry}
\begin{entry}{%
\proto{basename}{ string} {procedure}}
\saut
Returns a string containing the last component of the path name given in
\var{string}.
\begin{scheme}
(basname "/a/b/c.stk") \lev "c.stk"
\end{scheme}
\end{entry}
\begin{entry}{%
\proto{decompose-file-name}{ string} {procedure}}
\saut
Returns an ``exploded'' list of the path name components given in
\var{string}.
The first element in the list denotes if the given \var{string} is an
absolute path or a relative one, being {\tt "/"} or {\tt "."} respectively.
Each component of this list is a string.
\begin{scheme}
(decompose-file-name "/a/b/c.stk") \lev ("/" "a" "b" "c.stk")
(decompose-file-name "a/b/c.stk") \lev ("." "a" "b" "c.stk")
\end{scheme}
\end{entry}
\begin{entry}{%
\proto{file-is-directory?}{ string} {procedure}
\proto{file-is-regular?}{ string} {procedure}
\proto{file-is-readable?}{ string} {procedure}
\proto{file-is-writable?}{ string} {procedure}
\proto{file-is-executable?}{ string} {procedure}
\proto{file-exists?}{ string} {procedure}}
\saut
Returns {\schtrue} if the predicate is true for the path name given in
\var{string}; returns {\schfalse} otherwise (or if \var{string} denotes a file
which does not exist).
\end{entry}
\begin{entry}{%
\proto{glob}{ \vri{pattern} \vrii{pattern} \dotsfoo} {procedure}}
\saut
%%%%%%%%%%%%%% Irgendwann h"alt Gott seine Arme auf:
%%%%%%%%%%%%%% BIS HIERHIN UND NICHT WEITER!
The code for \ide{glob} is taken from the Tcl library. It performs
file name ``globbing'' in a fashion similar to the csh shell.
\ide{Glob} returns a list of the filenames that match at least one of
the {\em pattern} arguments. The \var{pattern} arguments may contain
the following special characters:
\begin{itemize}
\item ? Matches any single character.
\item \etoile~Matches any sequence of zero or more characters.
\item {\leftbracket}chars\rightbracket~Matches any single character in chars.
If chars contains a sequence of the form {\tt a-b} then any character between
{\tt a} and {\tt b} (inclusive) will match.
\item \verb+\+x Matches the character {\tt x}.
\item \{a,b,...\} Matches any of the strings {\tt a}, {\tt b}, etc.
\end{itemize}
As with csh, a ``.'' at the beginning of a file's name or just after a ``/''
must be matched explicitly or with a \{\} construct. In addition, all ``/''
characters must be matched explicitly.
If the first character in a pattern is ``{\tilda}'' then it refers to
the home directory of the user whose name follows the ``{\tilda}''.
If the ``{\tilda}'' is followed immediately by ``/'' then the value of
the environment variable HOME is used.
\ide{Glob} differs from csh globbing in two ways. First, it does not
sort its result list (use the \ide{sort} procedure if you want the list sorted).
Second, glob only returns the names of files that actually exist; in csh no
check for existence is made unless a pattern contains a ?, \etoile, or
\leftbracket\rightbracket
construct.
\end{entry}
\begin{entry}{%
\proto{getcwd}{ string} {procedure}}
\saut
\ide{Getcwd} returns a string containing the current working directory.
\end{entry}
\begin{entry}{%
\proto{chdir}{ string} {procedure}}
\saut
\ide{Chdir} changes the current directory to the directory given in
\var{string}.
\end{entry}
\begin{entry}{%
\proto{getpid}{ string} {procedure}}
\saut
Returns the system process number of the current {\stk} interpreter (i.e. the
Unix {\em pid}). Result is an integer.
\end{entry}
\begin{entry}{%
\proto{system}{ string} {procedure}
\proto{!}{ string} {procedure}}
\saut
Sends the given \var{string} to the system shell \var{/bin/sh}. The result of
\ide{system} is the integer status code the shell returns.
\end{entry}
\begin{entry}{%
\proto{exec}{ string} {procedure}}
\saut
Executes the command contained in \var{string} and redirects its output in
a string. This string constitutes the result of \ide{exec}.
\end{entry}
\begin{entry}{%
\proto{getenv}{ string} {procedure}}
\saut
Looks for the environment variable named \var{string} and returns its
value as a string, if it exists. Otherwise, \ide{getenv} returns
{\schfalse}.
\begin{scheme}
(getenv "SHELL") \lev "/bin/zsh"
\end{scheme}
\end{entry}
\begin{entry}{%
\proto{setenv!}{ var value} {procedure}}
\saut
Sets the environment variable \var{var} to \var{value}. \var{Var} and
\var{value} must be strings. The result of {\tt setenv!} is undefined.
\begin{scheme}
(getenv "SHELL") \lev "/bin/zsh"
\end{scheme}
\end{entry}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%
%%%% Section 6.16: Addresses
%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{Addresses}
\label{addresses}
An {\em address} is a Scheme object which contains a reference to
another Scheme object. This type can be viewed as a kind of pointer to
a Scheme object. Addresses, even though they are very dangerous, have
been introduced in {\stk} so that objects that have no ``readable''
external representation can still be transformed into strings and back
without loss of information. Adresses were useful with pre-3.0 version
of {\stk}; their usage is now {\bf stongly discouraged}, unless you know what you
do. In particular, an address can designate an object at a time and
another one later (i.e. after the garbage collector has marked the zone
as free).
Addresses are printed with a special syntax: {\tt {\sharpsign}pNNN},
where {\tt NNN} is an hexadecimal value. Reading this value back
yields the original object whose location is {\tt NNN}.
\begin{entry}{%
\proto{address-of}{ obj} {procedure}}
\saut
Returns the address of \ide{obj}.
\end{entry}
\begin{entry}{%
\proto{address?}{ obj} {procedure}}
\saut
Returns {\schtrue} if \var{obj} is an address; returns {\schfalse} otherwise.
\end{entry}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%
%%%% Section 6.17: Signals
%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{Signals}
\label{signals}
{\stk} allows the use to associate handlers to signals. Signal
handlers for a given signal can even be chained in a list. When a
signal occurs, the first signal of the list is executed. Unless this
signal yields the symbol \ide{break} the next signal of the list is
evaluated. When a signal handler is called, the integer value of this
signal is passed to it as (the only) parameter.
The following POXIX.1\mainindex{POSIX.1} constants for signal numbers
are defined: \ide{SIGABRT}, \ide{SIGALRM}, \ide{SIGFPE}, \ide{SIGHUP},
\ide{SIGILL}, \ide{SIGINT}, \ide{SIGKILL}, \ide{SIGPIPE}, {\tt
SIGQUIT}, \ide{SIGSEGV}, \ide{SIGTERM}, \ide{SIGUSR1}, {\tt
SIGUSR2}, \ide{SIGCHLD}, \ide{SIGCONT}, \ide{SIGSTOP}, {\tt
SIGTSTP}, \ide{SIGTTIN}, \ide{SIGTTOU}. Moreover, the following
constants, which are often available on most systems are also
defined\footnote{Some of these constants may be undefined if they are
not supported by your system}: \ide{SIGTRAP}, \ide{SIGIOT}, {\tt
SIGEMT}, \ide{SIGBUS}, \ide{SIGSYS}, \ide{SIGURG}, \ide{SIGCLD},
\ide{SIGIO}, \ide{SIGPOLL}, \ide{SIGXCPU}, \ide{SIGXFSZ}, {\tt
SIGVTALRM}, \ide{SIGPROF}, \ide{SIGWINCH}, \ide{SIGLOST}.
See your Unix documentation for the exact meaning of each constant or
\cite{Posix.1-90}. Use symbolic constants rather than their numeric
value if you plan to port your program on another system.
\label{GCSTART}
A special signal, managed by the interpreter, is also defined: {\tt
SIGHADGC}. This signal is raised when the garbage collector phase
terminates.
When the interpreter starts running, all signals are sets to their
default value, excepted \ide{SIGINT} (generally bound to {\ide
Control-C}) which is handled specially.
\begin{entry}{%
\proto{set-signal-handler!}{ sig handler} {procedure}}
\saut
Replace the handler for signal \var{sig} with \var{handler}.
Handler can be
\begin{itemize}
\item [-] {\schtrue} to reset the signal handler for \var{sig} to the
default system handler.
\item [-] {\schfalse} to completly ignore \var{sig} (Note that
Posix.1 states that \ide{SIGKILL} and \ide{SIGSTOP} cannot be caught
or ignored).
\item [-] a one parameter procedure.
\end{itemize}
This procedure returns the new handler, or (length 1) handler list,
associated to \var{sig}.
\begin{scheme}
(let* ((x \schfalse)
(handler (lambda (i) (set! x \schtrue))))
(set-signal-handler! |SIGHADGC| handler)
(gc)
x) \lev \schtrue
\end{scheme}
\end{entry}
\begin{entry}{%
\proto{add-signal-handler!}{ sig handler} {procedure}}
\saut
Adds \var{handler} to the list of handlers for signal \var{sig}. If
the old signal handler is a boolean, this procedure is equivalent to
\ide{set-signal-handler!}. Otherwise, the new handler is added in
front of the previous list of handler. This procedure returns the new
handler, or handler list, associated to \var{sig}.
\begin{scheme}
(let* ((x '())
(handler1 (lambda (i) (set! x (cons 1 x))))
(handler2 (lambda (i) (set! x (cons 2 x)))))
(add-signal-handler! |SIGHADGC| handler1)
(add-signal-handler! |SIGHADGC| handler2)
(gc)
x) \lev (1 2)
\end{scheme}
\saut
\begin{scheme}
(let* ((x '())
(handler1 (lambda (i) (set! x (cons 1 x))))
(handler2 (lambda (i) (set! x (cons 2 x)) 'break)))
(add-signal-handler! |SIGHADGC| handler1)
(add-signal-handler! |SIGHADGC| handler2)
(gc)
x) \lev (2)
\end{scheme}
\end{entry}
\begin{entry}{%
\proto{get-signal-handlers}{} {procedure}
\proto{get-signal-handlers}{ sig} {procedure}}
\saut
Returns the handlers, or the list of handlers, associated to the signal
\var{sig}. If \var{sig} is omitted, \ide{get-signal-handlers} returns
a vector of all the signal handlers currently in effect.
\end{entry}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%
%%%% Section 6.18: Hash tables
%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{Hash tables}
\label{hashtables}
A hash table consists of zero or more entries, each consisting of a key and a
value. Given the key for an entry, the hashing function can very quickly
locate the entry, and hence the corresponding value. There may be at most one
entry in a hash table with a particular key, but many entries may have the
same value.
{\stk} hash tables grow gracefully as the number of entries increases, so that
there are always less than three entries per hash bucket, on average. This
allows for fast lookups regardless of the number of entries in a table.
\vskip3mm
\begin{note}
Hash table manipulation procedures are built upon the efficient Tcl hash
table package.
\end{note}
\begin{entry}{
\proto{make-hash-table}{}{ procedure}
\proto{make-hash-table}{ comparison}{ procedure}
\proto{make-hash-table}{ comparison hash}{ procedure}}
\saut
\ide{Make-hash-table} admits three different forms.
The most general form admit two arguments. The first argument is a
comparison function which determine how keys are compared; the second
argument is a function which computes a hash code for an object and
returns the hash code as a non negative integer. Objets with the same
hash code are stored in an A-list registered in the bucket
corresponding to the key.
If omitted,
\begin{itemize}
\item {\tt hash} defaults to the \ide{hash-table-hash}
procedure.
\item {\tt comparison } defaults to the \ide{eq?} procedure
\end{itemize}
Consequently,
\begin{scheme}
(define h (make-hash-table))
\end{scheme}
is equivalent to
\begin{scheme}
(define h (make-hash-table eq? hash-table-hash))
\end{scheme}
Another interesting example is
\begin{scheme}
(define h (make-hash-table string-ci=? string-length))
\end{scheme}
which defines a new hash table which uses {\tt string-ci=?} for
comparing keys. Here, we use the string-length as a (very simple)
hashing function. Of course, a function which gives a key depending
of the characters composing the string gives a better repartition
and should probably enhance performances. For instance, the following
call to {\tt make-hash-table} should return a more efficient, even if
not perfect, hash table:
\begin{scheme}
(make-hash-table
string-ci=?
(lambda (s)
(let ((len (string-length s)))
(do ((h 0) (i 0 (+ i 1)))
((= i len) h)
(set! h (+ h (char->integer
(char-downcase (string-ref s i)))))))))
\end{scheme}
\begin{note}
Hash tables with a comparison function equal to \ide{eq?} or {\tt
string=?} are handled in an more efficient way (in fact, they
don't use the \ide{hash-table-hash} fucntion to speed up hash table
retrievals).
\end{note}
\end{entry}
\begin{entry}{
\proto{hash-table?}{ obj}{ procedure}}
\saut
Returns {\schtrue} if \var{obj} is a hash table, returns {\schfalse} otherwise.
\end{entry}
\begin{entry}{
\proto{hash-table-hash}{ obj}{ procedure}}
\saut
\ide{hash-table-hash} computes a hash code for an object and returns
the hash code as a non negative integer. A property of {\tt
hash-table-hash} is that
\begin{quote}
{\tt (equal? x y)} implies {\tt (equal? (hash-table-hash x) (hash-table-hash y)}
\end{quote}
as the the Common Lisp {\tt sxhash} function from which this procedure is
modeled.
\end{entry}
\begin{entry}{
\proto{hash-table-put!}{ hash key value}{ procedure}}
\saut
\ide{Hash-table-put!} enters an association between \var{key} and \var{value} in the
\var{hash} table. The value returned by \ide{hash-table-put!} is undefined.
\end{entry}
\begin{entry}{
\proto{hash-table-get}{ hash key}{ procedure}
\proto{hash-table-get}{ hash key default}{ procedure}}
\saut
\ide{Hash-table-get} returns the value associated with \var{key} in
the given \var{hash} table. If no value has been associated with \var{key} in
\var{hash}, the specified \var{default} is returned if given; otherwise an
error is raised.
\begin{scheme}
(define h1 (make-hash-table))
(hash-table-put! h1 'foo (list 1 2 3))
(hash-table-get h1 'foo) \lev (1 2 3)
(hash-table-get h1 'bar 'absent) \lev absent
(hash-table-get h1 'bar) \lev \scherror
(hash-table-put! h1 '(a b c) 'present)
(hash-table-get h1 '(a b c) 'absent) \lev 'absent
(define h2 (make-hash-table equal?))
(hash-table-put! h2 '(a b c) 'present)
(hash-table-get h2 '(a b c)) \lev 'present
\end{scheme}
\end{entry}
\begin{entry}{
\proto{hash-table-remove!}{ hash key}{ procedure}}
\saut
\var{hash} must be a hash table containing an entry for \var{key}.
\ide{Hash-table-remove!} deletes the entry for \var{key} in
\var{hash}, if it exists. Result of {\tt Hash-table-remove!} is unspecified.
\begin{scheme}
(define h (make-hash-table))
(hash-table-put! h 'foo (list 1 2 3))
(hash-table-get h 'foo) \lev (1 2 3)
(hash-table-remove! h 'foo)
(hash-table-get h 'foo 'absent) \lev absent
\end{scheme}
\end{entry}
\begin{entry}{
\proto{hash-table-for-each}{ hash proc}{procedure}}
\saut %
\var{Proc} must be a procedure taking two arguments.
\ide{Hash-table-for-each} calls \var{proc} on each key/value
association in \var{hash}, with the key as the first argument and the
value as the second. The value returned by \ide{hash-table-for-each}
is undefined.
\vskip3mm
\begin{note}
The order of application of \var{proc} is unspecified.
\end{note}
\begin{scheme}
(let ((h (make-hash-table))
(sum 0))
(hash-table-put! h 'foo 2)
(hash-table-put! h 'bar 3)
(hash-table-for-each h (lambda (key value)
(set! sum (+ sum value))))
sum) \lev 5
\end{scheme}
\end{entry}
\begin{entry}{
\proto{hash-table-map}{ hash proc}{procedure}}
\saut %
\var{Proc} must be a procedure taking two arguments.
\ide{Hash-table-map} calls \var{proc} on each entry in \var{hash},
with the entry's key as the first argument and the entry's value as
the second. The result of \ide{hash-table-map} is a list of the
values returned by \var{proc}, in unspecified order. %
\vskip3mm
\begin{note}
The order of application of \var{proc} is unspecified.
\end{note}
\begin{scheme}
(let ((h (make-hash-table)))
(dotimes (i 5)
(hash-table-put! h i (number->string i)))
(hash-table-map h (lambda (key value)
(cons key value)))) \lev ((0 . "0") (3 . "3") (2 . "2") (1 . "1") (4 . "4"))
\end{scheme}
\end{entry}
\begin{entry}{
\proto{hash-table->list}{ hash}{ procedure}}
\saut %
\ide{hash-table->list} returns an ``association list'' built from the
entries in \var{hash}. Each entry in \var{hash} will be represented
as a pair whose \var{car} is the entry's key and whose \var{cdr} is
its value.
\begin{note}
The order of pairs in the resulting list is unspecified.
\end{note}
\begin{scheme}
(let ((h (make-hash-table)))
(dotimes (i 5)
(hash-table-put! h i (number->string i)))
(hash-table->list h)) \lev ((0 . "0") (3 . "3") (2 . "2") (1 . "1") (4 . "4"))
\end{scheme}
\end{entry}
\begin{entry}{
\proto{hash-table-stats}{ hash}{procedure}}
\saut %
\ide{Hash-table-stats} returns a string with overall information about
\var{hash}, such as the number of entries it contains, the number of
buckets in its hash array, and the utilization of the buckets.
\end{entry}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%
%%%% Section 6.19: Regular Expressions
%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{Regular expressions}
\label{regexp-type}
Regular expressions\mainindex{regular expression} are first class objects in
{\stk}. A regular expression is created by the \ide{string->regexp}
procedure. Matching a regular expression against a string is simply done by
applying a previously created regular expression to this string.
Regular expressions are implemented using code in the Henry Spencer's
package, and much of the description of regular expressions below is copied
from his manual.
\begin{entry}{
\proto{string->regexp}{ string}{procedure}}
\saut
\ide{String->regexp} compiles the \var{string} and returns the
corresponding regular expression.
\smallskip
Matching a regular expression against a string is done by applying the result
of \ide{string->regexp} to this string. This application yields a list of
integer couples if a matching occurs; it returns {\schfalse} otherwise. Those
integers correspond to indexes in the string which match the regular
expression.
A regular expression is zero or more {\em branches}, separated by ``{\tt |}''. It
matches anything that matches one of the branches.
A branch is zero or more {\em pieces}, concatenated. It matches a match for
the first, followed by a match for the second, etc.
A piece is an {\em atom} possibly followed by ``{\tt *}'', ``{\tt +}'', or
``{\tt ?}''. An atom followed by ``{\tt *}'' matches a sequence of 0 or more
matches of the atom. An atom followed by ``{\tt +}'' matches a sequence of 1
or more matches of the atom. An atom followed by ``{\tt ?}'' matches a match
of the atom, or the null string.
An atom is a regular expression in parentheses (matching a match for the
regular expression), a {\em range} (see below), ``{\tt .}'' (matching any
single character), ``{\tt \verb+^+}'' (matching the null string at the
beginning of the input string), ``{\tt \verb|$|}'' % $
(matching the null string
at the end of the input string), a ``{\tt \verb+\+}'' followed by a single
character (matching that character), or a single character with no other
significance (matching that character).
A {\em range} is a sequence of characters enclosed in ``{\tt []}''. It
normally matches any single character from the sequence. If the sequence
begins with ``{\tt \verb+^+}'', it matches any single character {\em not} from
the rest of the sequence. If two characters in the sequence are separated by
``{\tt -}'', this is shorthand for the full list of ASCII characters between
them (e.g. ``{\tt [0-9]}'' matches any decimal digit). To include a literal
``{\tt ]}'' in the sequence, make it the first character (following a possible
``{\tt \verb+^+}''). To include a literal ``{\tt -}'', make it the first or
last character.
In general there may be more than one way to match a regular expression to an
input string. Considering only the rules given so far could lead to
ambiguities. To resolve those ambiguities, the generated regular expression
chooses among alternatives using the rule ``first then longest''. In other
words, it considers the possible matches in order working from left to right
across the input string and the pattern, and it attempts to match longer
pieces of the input string before shorter ones. More specifically, the
following rules apply in decreasing order of priority:
\begin{enumerate}
\item If a regular expression could match two different parts of an
input string then it will match the one that begins earliest.
\item If a regular expression contains ``{\tt |}'' operators then the leftmost
matching sub-expression is chosen.
\item In ``{\tt *}'', ``{\tt +}'', and ``{\tt ?}'' constructs, longer matches are chosen
in preference to shorter ones.
\item In sequences of expression components the components are considered
from left to right.
\end{enumerate}
\begin{scheme}
(define r1 (string->regexp "abc"))
(r1 "xyz") \ev \schfalse
(r1 "12abc345") \ev ((2 5))
(define r2 (string->regexp "[a-z]+"))
(r2 "12abc345") \ev ((2 5))
\end{scheme}
If the regular expression contains parenthesis, and if there is a match, the
result returned by the application will contain several couples of integers.
First couple will be the indexes of the first longest substring which match
the regular expression. Subsequent couples, will be the indexes of all the
sub-parts of this regular expression, in sequence.
\begin{scheme}
(define r3 (string->regexp "(a*)(b*)c"))
(r3 "abc") \ev ((0 3) (0 1) (1 2))
(r3 "c") \ev ((0 1) (0 0) (0 0))
((string->regexp "([a-z]+),([a-z]+)") "XXabcd,eXX")
\ev ((2 8) (2 6) (7 8))
\end{scheme}
\end{entry}
\begin{entry}{
\proto{regexp?}{ obj}{procedure}}
\saut
Returns \schtrue{} if \var{obj} is a regular expression created by
\ide{string->regexp}; otherwise returns {\schfalse}.
\begin{scheme}
(regexp? (string->regexp "[a-zA-Z][a-zA-Z0-9]*"))
\ev \schtrue
\end{scheme}
\end{entry}
\begin{entry}{
\proto{regexp-replace}{ pattern string substitution}{procedure}
\proto{regexp-replace-all}{ pattern string substitution}{procedure}}
\saut
\ide{Regexp-replace} matches the regular expression \var{pattern} against
\var{string}. If there is a match, the portion of \var{string} which match
\var{pattern} is replaced by the \var{substitution} string. If there is no match,
\ide{regexp-replace} returns \var{string} unmodified. Note that the given
\var{pattern} could be here either a string or a regular expression.
\smallskip
If \var{pattern} contains strings of the form ``{\tt \verb+\+n}'',
where {\em n} is a digit between 1 and 9, then it is replaced in the
substitution with the portion of string that matched the {\em n}-th
parenthesized subexpression of {\em pattern}. If {\em n} is equal to
0, then it is replaced in \var{substitution} with the portion of
\var{string} that matched \var{pattern}.
\begin{scheme}
(regexp-replace "a*b" "aaabbcccc" "X")
\ev "Xbcccc"
(regexp-replace (string->regexp "a*b") "aaabbcccc" "X")
\ev "Xbcccc"
(regexp-replace "(a*)b" "aaabbcccc" "X\verb+\\+1Y")
\ev "XaaaYbcccc"
(regexp-replace "(a*)b" "aaabbcccc" "X\verb+\\+0Y")
\ev "XaaabYbcccc"
(regexp-replace "([a-z]*) ([a-z]*)" "john brown" "\verb+\\2 \\1+")
\ev "brown john"
\end{scheme}
\ide{Regexp-replace} replaces the first occurence of \var{pattern} in
\var{string}. To replace {\em all} the occurences of the {\em pattern}, use
\ide{regexp-replace-all}
\begin{scheme}
(regexp-replace "a*b" "aaabbcccc" "X")
\ev "Xbcccc"
(regexp-replace-all "a*b" "aaabbcccc" "X")
\ev "XXcccc"
\end{scheme}
\end{entry}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%
%%%% Section 6.20: Processes
%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{Processes}
\label{process-type}
{\stk} provides access to Unix processes as first class objects. Basically,
a process contains four informations: the standard Unix process
identification (aka PID\mainindex{PID}) and the three standard files
of the process.
\begin{entry}{
\proto{run-process}{ command \vri{p} \vrii{p} \vriii{p} \dotsfoo}{procedure}}
\saut
\ide{run-process} creates a new process and run the executable
specified in \var{command}. The \var{p} correspond to the command line
arguments. The following values of \var{p} have a special meaning:
\begin{itemize}
\item {\tt :input} permits to redirect the standard input file of the
process. Redirection can come from a file or from a pipe. To redirect
the standard input from a file, the name of this file must be
specified after {\tt :input}. Use the special keyword {\tt :pipe} to
redirect the standard input from a pipe.
\item {\tt :output} permits to redirect the standard output file of the
process. Redirection can go to a file or to a pipe. To redirect
the standard output to a file, the name of this file must be
specified after {\tt :output}. Use the special keyword {\tt :pipe} to
redirect the standard output to a pipe.
\item {\tt :error} permits to redirect the standard error file of the
process. Redirection can go to a file or to a pipe. To redirect
the standard error to a file, the name of this file must be
specified after {\tt :error}. Use the special keyword {\tt :pipe} to
redirect the standard error to a pipe.
\item {\tt :wait} must be followed by a boolean value. This value
specifies if the process must be run asynchronously or not. By
default, the process is run asynchronously (i.e. {\tt :wait} is
\schfalse).
\item {\tt :host} must be followed by a string. This string represents
the name of the machine on which the command must be executed. This
option uses the external command {\tt rsh}. The shell variable {\tt
PATH} must be correctly set for accessing it without specifying its
abolute path.
\end{itemize}
The following example launches a process which execute the
Unix command {\tt ls} with the arguments {\tt -l} and {\tt
/bin}. The lines printed by this command are stored in the file {\tt /tmp/X}
\begin{scheme}
(run-process "ls" "-l" "/bin" :output "/tmp/X" :wait \schfalse)
\end{scheme}
\end{entry}
\begin{entry}{
\proto{process?}{ process}{procedure}}
\saut
Returns \schtrue{} if \var{process} is a process, otherwise returns
{\schfalse}.
\end{entry}
\begin{entry}{
\proto{process-alive?}{ process}{procedure}}
\saut
Returns \schtrue{} if \var{process} if the process is currently running,
otherwise returns {\schfalse}.
\end{entry}
\begin{entry}{
\proto{process-pid}{ process}{procedure}}
\saut
Returns an integer value which represents the Unix identification
(PID\mainindex{PID}) of \var{process}.
\end{entry}
\begin{entry}{
\proto{process-input}{ process}{procedure}
\proto{process-output}{ process}{procedure}
\proto{process-error}{ process}{procedure}}
\saut
Returns the file port associated to the standard input, output or error
of \var{process}, if it is redirected in (or to) a pipe; otherwise
returns \schfalse. Note that the returned port is opened for reading
when calling {\tt process-output} or {\tt process-error}; it is opened
for writing when calling {\tt process-input}.
\end{entry}
\begin{entry}{
\proto{process-wait}{ process}{procedure}}
\saut
\ide{Process-wait} stops the current process until
\var{process} completion. \ide{Process-wait} returns {\schfalse}
when \var{process} is already terminated; it returns {\schtrue} otherwise.
\end{entry}
\begin{entry}{
\proto{process-exit-status}{ process}{procedure}}
\saut
\ide{Process-exit-status} returns the exit status of \var{process} if
it has finished its execution; returns {\schfalse} otherwise.
\end{entry}
\begin{entry}{
\proto{process-send-signal}{ process n}{procedure}}
\saut
Send the signal whose integer value is \var{n} to \var{process}. Value
of \var{n} is system dependant. Use the defined signal constants to
make your program indpendant of the running system (see
\ref{signals}). The result of \var{process-send-signal} is undefined.
\end{entry}
\begin{entry}{
\proto{process-kill}{ process}{procedure}}
\saut
\ide{Process-kill} brutally kills \var{process}. The result of
\ide{process-kill}
is undefined. This procedure is equivalent to
\begin{scheme}
(process-send-signal process |SIGTERM|)
\end{scheme}
\end{entry}
\begin{entry}{
\proto{process-stop}{ process}{procedure}
\proto{process-continue}{ process}{procedure}}
\saut
Those procedures are only available on systems which support job
control. \var{Process-stop} stops the execution of
\var{process} and \var{process-continue} resumes its execution. They
are equivalent to
\begin{scheme}
(process-send-signal process |SIGSTOP|)
(process-send-signal process |SIGCONT|)
\end{scheme}
\end{entry}
\begin{entry}{
\proto{process-list}{}{procedure}}
\saut
\ide{process-list} returns the list of processes which are currently
running (i.e. alive).
\end{entry}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%
%%%% Section 6.21: Sockets
%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{Sockets}
\label{socket-type}
{\stk} defines sockets, on systems which support them, as first class
objects. Sockets permits processes to communicate even if they are on
different machines. Sockets are useful for creating client-server
applications.
\begin{entry}{
\proto{make-client-socket}{ hostname port-number}{procedure}}
\saut
\ide{make-client-socket} returns a new socket object. This socket
establishes a link between the running application listening on port
\var{port-number} of \var{hostname}.
\end{entry}
\begin{entry}{
\proto{socket?}{ socket}{procedure}}
\saut
Returns \schtrue{} if \var{socket} is a socket, otherwise returns
{\schfalse}.
\end{entry}
\begin{entry}{
\proto{socket-host-name}{ socket}{procedure}}
\saut
Returns a string which contains the name of the distant host attached to
\var{socket}. If \var{socket} has been created with \ide{make-client-socket}
this procedure returns the official name of the distant machine used for
connection. If \var{socket} has been created with \ide{make-server-socket},
this function returns the official name of the client connected to the socket.
If no client has used yet the socket, this function returns \schfalse.
\end{entry}
\begin{entry}{
\proto{socket-host-address}{ socket}{procedure}}
\saut
Returns a string which contains the IP\mainindex{IP number} number of
the distant host attached to \var{socket}. If \var{socket} has been
created with \ide{make-client-socket} this procedure returns the
IP number of the distant machine used for connection. If
\var{socket} has been created with \ide{make-server-socket}, this
function returns the address of the client connected to the
socket. If no client has used yet the socket, this function returns
\schfalse.
\end{entry}
\begin{entry}{
\proto{socket-local-address}{ socket}{procedure}}
\saut
Returns a string which contains the IP\mainindex{IP number} number of
the local host attached to \var{socket}.
\end{entry}
\begin{entry}{
\proto{socket-port-number}{ socket}{procedure}}
\saut
Returns the integer number of the port used for \var{socket}.
\end{entry}
\begin{entry}{
\proto{socket-input} { socket}{procedure}
\proto{socket-output}{ socket}{procedure}}
\saut
Returns the file port associated for reading or writing with the program
connected with \var{socket}. If no connection has already been established,
these functions return \schfalse.
The following example shows how to make a client socket. Here we create a
socket on port 13 of the machine ``{\tt kaolin.unice.fr}''\footnote{Port 13
is generally used for testing: making a connection to it permits to know
the distant system's idea of the time of day.}:
\begin{scheme}
(let ((s (make-client-socket "kaolin.unice.fr" 13)))
(format {\schtrue} "Time is: {\tilda}A\verb+\+n" (read-line (socket-input s)))
(socket-shutdown s))
\end{scheme}
\end{entry}
\begin{entry}{
\proto{make-server-socket}{}{procedure}
\proto{make-server-socket}{ port-number}{procedure}}
\saut
\ide{make-server-socket} returns a new socket object. If \var{port-number}
is specified, the socket is listening on the specified port; otherwise, the
communication port is choosen by the system.
\end{entry}
\begin{entry}{
\proto{socket-accept-connection}{ socket}{procedure}}
\saut
\ide{socket-accept-connection} waits for a client connection on the given
\var{socket}. If no client is already waiting for a connection, this
procedure blocks its caller; otherwise, the first connection request on the
queue of pending connections is connected to \var{socket}.
This procedure must be called on a server socket created
with \ide{make-server-socket}. The result of \ide{socket-accept-connection}
is undefined.
The following exemple is a simple server which waits for a connection
on the port 1234\footnote{Under Unix, you can simply connect to
listening socket with the {\tt telnet} command. With the given
example, this can be
achived by typing the following command in a window shell:\\
{\tt \$ telnet localhost 1234}}. Once the connection with the
distant program is established, we read a line on the input port
associated to the socket and we write the length of this line on its
output port.
\begin{scheme}
(let ((s (make-server-socket 1234)))
(socket-accept-connection s)
(let ((l (read-line (socket-input s))))
(format (socket-output s) "Length is: {\tilda}A\verb+\+n" (string-length l))
(flush (socket-output s)))
(socket-shutdown s))
\end{scheme}
\end{entry}
\begin{entry}{
\proto{socket-shutdown}{ socket}{procedure}
\proto{socket-shutdown}{ socket close}{procedure}}
\saut
\ide{Socket-shutdown} shutdowns the connection associated to \var{socket}.
\var{Close} is a boolean; it indicates if the socket must be close or not, when
the connection is dstroyed. Closing the socket forbids further connections on
the same port with the \ide{socket-accept-connection} procedure.
Omitting a value for \var{close} implies the closing of socket.
The result of \ide{socket-shutdown} is undefined.
The following example shows a simple server: when there is a new connection
on the port number 1234, the server displays the first line sent to it by the
client, discards the others and go back waiting for further client connections.
\begin{scheme}
(let ((s (make-server-socket 1234)))
(let loop ()
(socket-accept-connection s)
(format {\schtrue} "I've read: {\tilda}A\verb+\+n" (read-line (socket-input s)))
(socket-shutdown s \schfalse)
(loop)))
\end{scheme}
\end{entry}
\begin{entry}{
\proto{socket-down?}{ socket}{procedure}}
\saut
Returns {\schtrue} if \var{socket} has been previously closed
with \ide{socket-shutdown}. It returns {\schfalse} otherwise.
\end{entry}
\begin{entry}{
\proto{socket-dup}{ socket}{procedure}}
\saut
Returns a copy of \var{socket}. The original and the copy socket can be used
interchangeably. However, if a new connection is accepted on one socket,
the characters exchanged on this socket are not visible on the other socket.
Duplicating a socket is useful when a server must accept multiple simultaneous
connections.
The following example creates a server listening on port 1234. This server is
duplicated and, once two clients are present, a message is sent on both
connections.
\begin{scheme}
(define s1 (make-server-socket 1234))
(define s2 (socket-dup s1))
(socket-accept-connection s1)
(socket-accept-connection s2)
;; blocks until two clients are present
(display "Hello,\verb+\+n" (socket-output s1))
(display "world\verb+\+n" (socket-output s2))
(flush (socket-output s1))
(flush (socket-output s2))
\end{scheme}
\end{entry}
\begin{entry}{
\proto{when-socket-ready}{ socket handler}{procedure}
\proto{when-socket-ready}{ socket}{procedure}}
\saut
Defines a handler for \var{socket}. The handler is a thumk which is
executed when a connection is available on \var{socket}. If the special value
\schfalse{} is provided as \var{handler}, the current handler for \var{socket}
is deleted. If a handler is provided, the value returned by
\ide{when-socket-ready} is undefined. Otherwise, it
returns the handler currently associated to \var{socket}.
This procedure, in conjonction with \ide{socket-dup} permits to build
multiple-clients servers which work asynchronously. Such a server is
shown below.
\begin{scheme}
(define p (make-server-socket 1234))
(when-socket-ready p
(let ((count 0))
(lambda ()
(set! count (+ count 1))
(register-connection (socket-dup p) count))))
(define register-connection
(let ((sockets '()))
(lambda (s cnt)
;; Accept connection
(socket-accept-connection s)
;; Save socket somewhere to avoid GC problems
(set! sockets (cons s sockets))
;; Create a handler for reading inputs from this new connection
(let ((in (socket-input s))
(out (socket-output s)))
(when-port-readable in
(lambda ()
(let ((l (read-line in)))
(if (eof-object? l)
;; delete current handler
(when-port-readable in \schfalse)
;; Just write the line read on the socket
(begin
(format out "On {\sharpsign}{\tilda}A --> {\tilda}A\verb+\+n" cnt l)
(flush out))))))))))
\end{scheme}
\end{entry}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%
%%%% Section 6.22: Misc
%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{Miscellaneous}
This section lists the primitives defined in {\stk} that did not fit
anywhere else.
\begin{entry}{
\proto{eval}{ \hyper{expr}}{syntax}
\proto{eval}{ \hyper{expr} \hyper{environment}}{syntax}}
\saut
Evaluates \hyper{expr} in the given environment. \hyper{Environment} may be
omitted, in which case it defaults to the global environment.
\begin{scheme}
(define foo (let ((a 1)) (lambda () a)))
(foo) \ev 1
(eval '(set! a 2) (procedure-environment foo))
(foo) \ev 2
\end{scheme}
\end{entry}
\begin{entry}{
\proto{version}{} {procedure}}
\saut
returns a string identifying the current version of {\stk}.
\end{entry}
\begin{entry}{
\proto{machine-type}{} {procedure}}
\saut
returns a string identifying the kind of machine which is running the
interpreter. The form of the result is {\tt [os-name]-[os-version]-[processor-type]}.
\end{entry}
\begin{entry}{
\proto{random}{ n} {procedure}}
\saut
returns an integer in the range 0, $\var{n}-1$ inclusive.
\end{entry}
\begin{entry}{%
\proto{set-random-seed!} { seed} {procedure}}
\saut
Set the random seed to the specified \var{seed}. {\tt Seed} must be an integer
which fits in a C {\tt long int}.
\end{entry}
\begin{entry}{
\proto{eval-string}{ string environment} {procedure}}
\saut
Evaluates the contents of the given \var{string} in the given
\var{environment} and returns its result.
If \var{environment} is omitted it defaults to the global
environment. If evaluation leads to an error, the result of \ide{eval-string}
is undefined.
\begin{scheme}
(define x 1)
(eval-string "(+ x 1)") \lev 2
(eval-string "x" (let ((x 2)) (the-environment))) \lev 2
\end{scheme}
\end{entry}
\begin{entry}{
\proto{read-from-string}{ \hyper{string}} {procedure}}
\saut
Performs a read from the given \var{string}. If \var{string} is the empty
string, an end of file object is returned. If an error occurs during string
reading, the result of \ide{read-from-string} is undefined.
\begin{scheme}
(read-from-string "123 456") \lev 123
(read-from-string "") \lev an eof object
\end{scheme}
\end{entry}
\begin{entry}{
\proto{dump}{ string} {procedure}}
\saut
\ide{Dump} grabs the current continuation
\mainindex{continuation} and creates an image of the current {\stk}
interpreter in the file whose name is \var{string}{\footnote{
Image creation is not yet implemented on all systems. The current version
(\stkversion) allows image dumping only on some platforms:
SunOs~4.1.x, Linux~1, FreeBsd}}.
This image can be used later to restart the interpreter from the saved
state. See the {\stk} man page about the {\tt -image} option for more details.
\begin{note}
Image creation cannot be done if Tk is initialized.
\end{note}
\end{entry}
\begin{entry}{
\proto{trace-var}{ symbol thunk} {procedure}}
\saut
\ide{Trace-var} call the given \var{thunk} when the value
of the variable denoted by \var{symbol} is changed.
\begin{scheme}
(define x 1)
(define y 0)
(trace-var 'x (lambda () (set! y 1)))
(set! x 2)
(cons x y) \lev (2 . 1)
\end{scheme}
\begin{note}
Several traces can be associated with a single symbol. They are executed in
reverse order to their definition. For instance, the execution of
\begin{scheme}
(begin
(trace-var 'z (lambda () (display "One")))
(trace-var 'z (lambda () (display "Two")))
(set! z 10))
\end{scheme}
will display the string {\tt"Two"} before the string {\tt"One"} on the
current output port.
\end{note}
\end{entry}
\begin{entry}{
\proto{untrace-var}{ symbol} {procedure}}
\saut
Deletes all the traces associated to the variable denoted by \var{symbol}.
\end{entry}
\begin{entry}{
\proto{error}{ string \vri{string} \vrii{obj} \dotsfoo}{procedure}}
\saut
\ide{error} prints the \var{obj}s according to the specification given in
\var{string} on the current error port (or in an error window if Tk is
initialized\index{Tk toolkit}\index{toolkit}). The specification string
follows the ``tilde conventions'' of \ide{format}(see \ref{format}). Once the
message is printed, execution returns to toplevel.
\end{entry}
\begin{entry}{
\proto{gc}{}{procedure}}
\saut
Runs the garbage collector. See \ref{GCSTART} for the signals associated to
garbage collection.
\end{entry}
\begin{entry}{
\proto{gc-stats}{}{procedure}}
\saut %
Provides some statistics about current memory usage. This procedure is
primarily for debugging the {\stk} interpreter, hence its weird
printing format.
\end{entry}
\begin{entry}{
\proto{expand-heap}{ n}{procedure}}
\saut %
Expand the heap so that it will contains at least \var{n}
cells. Normally, the heap automatically grows when more memory is needed.
However, using only automatic heap growing is sometimes very penalizing.
This is particulary true for programs which uses a lot of temporary data
(which are not pointed by any a variable) and a small amount of global
data. In this case, the garbage collector will be often called and the heap
will not be automatically expanded (since most of the consumed heap will be
reclaimed by the GC). This could be annoying epecially for program where
response time is critical. Using \ide{expand-heap} permits to enlarge
the heap size (which is set to 20000 cells by default), to avoid those
continual calls to the GC.
\end{entry}
\begin{entry}{
\proto{get-internal-info}{}{procedure}}
\saut %
Returns a 7-length vector which contains the following informations:
\begin{enumerate}
\item[0] total cpu used in milli-seconds
\item[1] number of cells currently in use.
\item[2] total number of allocated cells
\item[3] number of cells used since the last call to \ide{get-internal-info}
\item[4] number of gc runs
\item[5] total time used in the gc
\item[6] a boolean indicating if Tk is initialized
\end{enumerate}
\end{entry}
\begin{entry}{
\proto{sort}{ obj predicate}{procedure}}
\saut
\var{Obj} must be a list or a vector. \ide{Sort} returns a copy of \var{obj} sorted
according to \var{predicate}. \var{Predicate} must be a procedure which takes
two arguments and returns a true value if the first argument is strictly ``before''
the second.
\begin{scheme}
(sort '(1 2 -4 12 9 -1 2 3) <)
\ev (-4 -1 1 2 2 3 9 12)
(sort \sharpsign("one" "two" "three" "four")
(lambda (x y) (> (string-length x) (string-length y))))
\ev \sharpsign("three" "four" "one" "two")
\end{scheme}
\end{entry}
\begin{entry}{
\label{uncode}
\proto{uncode}{ form}{procedure}}
\saut %
When {\stk} evaluates an expression it encodes it so that further
evaluations of this expression will be more efficient. Since encoded
forms are generally difficult to read, \ide{uncode} can be used to
(re-)obtain the original form.
\begin{scheme}
(define (foo a b)
(let ((x a) (y (+ b 1))) (cons x y)))
(procedure-body foo)
\ev (lambda (a b)
(let ((x a) (y (+ b 1))) (cons x y)))
(foo 1 2) \ev (1 . 3)
(procedure-body foo)
\ev (lambda (a b)
({\sharpsign}let (x y)
({\sharpsign}<local a @0,0)>
({\sharpsign}<global +> {\sharpsign}<local b @0,1)> 1))
({\sharpsign}<global cons> {\sharpsign}<local x @0,0)>
{\sharpsign}<local y @0,1)>)))
(uncode (procedure-body foo))
\ev (lambda (a b)
(let ((x a) (y (+ b 1))) (cons x y)))
\end{scheme}
\begin{note}
When a macro has been directly expanded into the macro call code, it is not
possible to retrieve the original macro call. Set \ide{*debug*} to
{\schtrue} to avoid macro expansion in-lining.
\end{note}
\end{entry}
\begin{entry}{
\proto{time} { \hyper{expr}}{macro}}
\saut
Evaluates the expression \hyper{expr} in the current environment. Prints the
elapsed CPU time and the number of conses used before returning the result of
this evaluation.
\end{entry}
\begin{entry}{%
\proto{apropos}{ symbol}{ procedure}}
\saut
\ide{Apropos} returns a list of symbol whose print name contains the characters
of \var{symbol}. Symbols are searched for in the current environment.
\begin{scheme}
(apropos 'cadd) \lev (caddar caddr cadddr)
\end{scheme}
\end{entry}
\begin{entry}{%
\proto{inspect}{ obj}{ procedure}}
\saut %
\ide{Inspect} permits to graphically inspect an object. The first call
of this procedure creates a top level window containing the object to
inspect and its current value. If the inspector window is already on
screen, \var{obj} will be appended to the list of inspected objects.
The inspector window contains menus which permit to call the viewer or
detailer on each inspected object. See the on-line documentation for
further details. A view of the general inspector is given in figure~1.
\begin{note}
Tk must be initialized to use \ide{inspect}.
\end{note}
\begin{figure}
\centerline{\psfig{figure={Inspector.ps}}}
\caption{A view of the Inspector}
\end{figure}
\end{entry}
\begin{entry}{%
\proto{view}{ obj}{ procedure}}
\saut %
\ide{View} permits to obtain a graphical representation of an {\stk}
object. The type of representation depends on the type of the viewed
object. Here again, menus are provided to switch to the inspector or
to the detailer. See the on-line documentation for more details. A
snapshot of the viewer is given in figure~2.
\begin{note}
Tk must be initialized to use \ide{view}.
\end{note}
\begin{figure}
\centerline{\psfig{figure={View.ps}}}
\caption{A view of the Viewer}
\end{figure}
\end{entry}
\begin{entry}{%
\proto{detail}{ obj}{ procedure}}
\saut %
\ide{detail} permits to display the fields of a composite Scheme
object. The type of detailer depends on the type of the composite
object detailed. Here again, menus are provided to go to the inspector
or to the viewer. See the on-line documentation for more details.
Figure~3 shows the detailer examining a {\em tk-command}.
\begin{note}
Tk must be initialized to use \ide{detail}.
\end{note}
\begin{figure}
\centerline{\psfig{figure={Detail.ps}}}
\caption{A view of the Detailer}
\end{figure}
\end{entry}
\begin{entry}{%
\proto{quit}{ retcode} {procedure}
\proto{quit}{} {procedure}
\proto{exit}{ retcode} {procedure}
\proto{exit}{} {procedure}
\proto{bye}{ retcode} {procedure}
\proto{bye}{} {procedure}}
\saut
Exits the {\stk} interpreter with the specified integer return code. If
omitted, the interpreter terminates with a return code of 0.
\end{entry}
%%% Local Variables:
%%% mode: latex
%%% TeX-master: "manual"
%%% End: