% % STk Reference manual (Part 2) % % Author: Erick Gallesio [eg@unice.fr] % Creation date: ??-Nov-1993 ??:?? % Last file update: 16-Aug-1999 20:21 % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%% %%%% 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: Modules %%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{Modules} \label{module} {\stk} modules can be used to organize a program into separate environments (or\textit{name spaces}). Modules provide a clean way to organize and enforce the barriers between the components of a program. {\stk} provides a simple module system which is largely inspired from the one of Tung and Dybvig exposed in \cite{Tung-Dybvig-96}. As their modules system, {\stk} modules are defined to be easily used in an interactive environment. \begin{entry}{% \proto{define-module}{ name \hyper{body}} {syntax}} \saut \var{Define-module} evaluates the expressions which are in \hyper{body} in the environment of the module \var{name}. \var{name} must be a valid symbol. If this symbol has not already been used to define a module, a new module, named \var{name}, is created. Otherwise, \hyper{body} is evaluated in the environment of the (old) module \var{name}\footnote{ In fact {\tt define-module} on a given name defines a new module only the first time it is invoked on this name. By this way, inteactively reloading a module does not define a new entity, and the other modules which use it are not altered.}. Definitions done in a module are local to the module and do not interact with the definitions of other modules. Consider the following definitions, \begin{scheme} (define-module M1 (define a 1)) (define-module M2 (define a 2) (define b (* 2 x))) \end{scheme} Here, two modules are defined and they both bind the symbol \texttt{a} to a value. However, since \texttt{a} has been defined in two distincts modules they denote two different locations. The ``\texttt{STk}'' module, which is predefined, is a special module which contains all the \textit{global variables} of a {\rrrr} program. A symbol defined in the \texttt{STk} module, if not hidden by a local definition, is always visible from inside a module. So, in the previous exemple, the \texttt{x} symbol refers the \texttt{x} symbol defined in the \texttt{STk} module. The result of \var{define-module} is undefined. \end{entry} \begin{entry}{% \proto{find-module}{ name} {procedure} \proto{find-module}{ name default} {procedure}} \saut {\stk} modules are first class objects and \ide{find-module} returns the module associated to \var{name} if it exists. If there is no module associated to \var{name}, an error is signaled if no \var{default} is provided, otherwise \ide{find-module} returns default. \end{entry} \begin{entry}{% \proto{module?}{ object} {procedure}} \saut Returns {\schtrue} if \var{object} is a module and {\schfalse} otherwise. \begin{scheme} (module? (find-module 'STk)) \lev \schtrue (module? 'STk) \lev \schfalse (module? 1) \lev \schfalse \end{scheme} \end{entry} \begin{entry}{% \proto{export}{ \hyperi{symbol} \hyperii{symbol}\ldots} {syntax}} \saut Specifies the symbols which are exported (i.e. \textit{visible}) outside the current module. By default, symbols defined in a module are not visible outside this module, excepted the symbols which appear in an \texttt{export} clause. If several \texttt{export} clauses appear in a module, the set of exported symbols is determined by {\em unioning} symbols exported in all the \texttt{export} clauses. The result of \var{export} is undefined. \end{entry} \begin{entry}{% \proto{import}{ \hyperi{module} \hyperii{module}\ldots} {syntax}} \saut Specifies the modules which are imported by the current module. Importing a module makes the symbols it exports visible to the importer, if not hidden by local definitions. When a symbol is exported by several of the imported modules, the location denoted by this symbol in the importer module correspond to the one of the first module in the list (\hyperi{module} \hyperii{module}\ldots) which export it. If several \texttt{import} clauses appear in a module, the set of imported modules is determined by appending the various list of modules in their apparition order. \begin{scheme} (define-module M1 (export a b) (define a 'M1-a) (define b 'M1-b)) (define-module M2 (export b c) (define b 'M2-b) (define c 'M2-c)) (define-module M3 (import M1 M2) (display (list a b c))) \lev displays (m1-a m1-b m2-c) \end{scheme} \begin{note} There is no kind of \emph{transitivity} in module importations: when the module $C$ imports the module $B$ which an importer of $A$, the symbols of $A$ are not visible from $C$, except by explicitly importing the $A$ module from $C$. \end{note} \begin{note} The module \texttt{STk}, which contains the \textit{global variables} is always implicitly imported from a module.Furthermore, this module is always placed at the end of the list of imported modules. \end{note} \end{entry} \begin{entry}{% \proto{export-symbol}{ symbol module} {procedure}} \saut Exports \var{symbol} from \var{module}. This procedure can be useful, when debugging a program, to make visible a given symbol without reloading or redefining the module where this symbol was defined. \end{entry} \begin{entry}{% \proto{export-all-symbols}{} {procedure}} \saut Exports all the symbols of current module . If symbols are added to the current \var{module} after the call to \ide{export-all-symbols}, they are automatically exported. \begin{note} The \texttt{STk} module export all the symbols which are defined in it (i.e. \textit{global variables} are visible, if not hidden, from all the modules of a program. \end{note} \end{entry} \begin{entry}{% \proto{with-module}{ name \hyperi{expr} \hyperii{expr} \ldots} {syntax}} \saut Evaluates the expressions of \hyperi{expr} \hyperii{expr} \ldots in the environment of module \var{name}. Module \var{name} must have been created previously by a \ide{define-module}. The result of \ide{with-module} is the result of the evaluation of the last \hyper{expr}. \begin{scheme} (define-module M (define a 1) (define b 2)) (with-module M (+ a b)) \lev 3 \end{scheme} \end{entry} \begin{entry}{% \proto{current-module}{} {procedure}} \saut Returns the current-module. \begin{scheme} (define-module M ...) (with-module M (cons (eq? (current-module) (find-module 'M)) (eq? (current-module) (find-module 'STk)))) \lev (\schtrue . \schfalse) \end{scheme} \end{entry} \begin{entry}{% \proto{select-module}{ name} {syntax}} \saut Evaluates the expressions which follows in module \var{name} environment. Module \var{name} must have been created previously by a \ide{define-module}. The result of \ide{select-module} is undefined. \ide{Select-module} is particularly useful when debugging since it allows to place toplevel evaluation in a particular module. The following transcript shows an usage of \ide{select-module}\footnote{This transcript uses the default value for the function \texttt{repl-display-prompt} (see page \pageref{repl-display-prompt}) which displays the name of the current module in the prompt.}: \begin{scheme} STk> (define foo 1) STk> (define-module bar (define foo 2)) STk> foo 1 STk> (select-module bar) bar> foo 2 bar> (select-module STk) STk> \end{scheme} \end{entry} \begin{entry}{% \proto{module-name}{ module} {procedure}} \saut Returns the name (a symbol) associated to a \var{module}. \end{entry} \begin{entry}{% \proto{module-imports}{ module} {procedure}} \saut Returns the list modules that \var{module} imports. \end{entry} \begin{entry}{% \proto{module-exports}{ module} {procedure}} \saut Returns the list of symbols exported by \var{module}. \end{entry} \begin{entry}{% \proto{module-symbols}{ module} {procedure}} \saut Returns the list symbols that ere defined in \var{module}. \end{entry} \begin{entry}{% \proto{all-modules}{ } {procedure}} \saut Returns a list of all the living modules. \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{module-environment}{ module} {procedure}} \saut Returns the environment associated to the module \var{module}. \begin{scheme} (define-module M (define a 1)) (car (environment->list (module-environment (find-module 'M)))) \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 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{remove-file}{ string} {procedure}} \saut Removes the file whose path name is given in \var{string}. The result of \ide{remove-file} is undefined. \end{entry} \begin{entry}{% \proto{rename-file}{ \vri{string} \vrii{string}} {procedure}} \saut Renames the file whose path-name is contained in \vri{string} in the path name given by \vrii{string}. The result of \ide{rename-file} is undefined. \end{entry} \begin{entry}{% \proto{temporary-file-name}{ string} {procedure}} \saut Generates a unique temporary file name. The value returned by \ide{temporary-file-name} is the newly generated name of {\schfalse} if a unique name cannot be generated. \end{entry} \begin{entry}{% \proto{getcwd}{} {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} \begin{entry}{% \proto{send-signal}{ sig} {procedure}} \saut Sends the signal \var{sig} to the running program. \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: Pattern matching %%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{Pattern matching} Pattern matching\mainindex{Pattern matching} is a key feature of most modern functional programming languages since it allows clean and secure code to be written. Internally, ``pattern-matching forms'' should be translated (compiled) into cascades of ``elementary tests'' where code is made as efficient as possible, avoiding redundant tests; the {\stk} ``pattern matching compiler'' provides this\footnote{The ``pattern matching compiler'' has been written by Jean-Marie Geffroy and is part of the Manuel Serrano's Bigloo compiler\cite{Serrano-97} since several years. The code (and documentation) included in {\stk} has been stolen from the Bigloo package v1.9 (the only difference between both package is the pattern matching of structures whisch is absent in {\stk}).}. The technique used is described in details in~\cite{Queinnec-Geffroy92}, and the code generated can be considered optimal due to the way this ``pattern compiler'' was obtained. The ``pattern language'' allows the expression of a wide variety of patterns, including: \begin{itemize} \item Non-linear patterns: pattern variables can appear more than once, allowing comparison of subparts of the datum (through {\tt eq?}) \item Recursive patterns on lists: for example, checking that the datum is a list of zero or more {\tt a}s followed by zero or more {\tt b}s. \item Pattern matching on lists as well as on vectors. \end{itemize} \subsubsection*{Pattern Matching Facilities} Only two special forms are provided for this: {\tt match-case} and {\tt match-lambda} and these also exist, for example, in Andrew Wright and Bruce Duba's~\cite{Wright-Duba-93} pattern matching package. \begin{entry}{ \proto{match-case}{ \hyper{key} \hyperi{clause} \hyperii{clause}\dotsfoo} {\exprtype}} \saut In this form, \hyper{key} may be any expression and each \hyper{clause} has the form \begin{scheme} ($<$pat$>$ $<$expression$_{1}$$>$ $<$expression$_{2}$$>$ \ldots) \end{scheme} A {\tt match-case} expression is evaluated as follows. $<$key$>$ is evaluated and the result is compared with each successive patterns. If the pattern in some $<$clause$>$ yields a match, then the expressions in that $<$clause$>$ are evaluated from left to right in an environment where the pattern variables are bound to the corresponding subparts of the datum, and the result of the last expression in that $<$clause$>$ is returned as the result of the {\tt match-case} expression. If no $<$pat$>$ in any $<$clause$>$ matches the datum, then, if there is an {\tt else} clause, its expressions are evaluated and the result of the last is the result of the whole {\tt match-case} expression; otherwise the result of the {\tt match-case} expression is unspecified. The equality predicate used is {\tt eq?}. \begin{scheme} (match-case '(a b a) ((?x ?x) 'foo) ((?x ?- ?x) 'bar)) \lev bar \end{scheme} \end{entry} \begin{entry}{ \proto{match-lambda}{ \hyperi{clause} \hyperii{clause}\dotsfoo} {\exprtype}} \saut The form \ide{match-lambda}expands into a lambda-expression expecting an argument which, once applied to an expression, behaves exactly like a {\tt match-case} expression. \begin{scheme} ((match-lambda ((?x ?x) 'foo) ((?x ?- ?x) 'bar)) 'bar) \lev bar \end{scheme} \end{entry} %*---------------------------------------------------------------------*/ \subsubsection*{The pattern language} The syntax is presented in Table~\ref{PatternLanguage}. It is described below in the same way (and nearly in the same words) as in \cite{Wright-Duba-93}. \begin{table} % [hptb] %\_\hrulefill\_ \begin{small} %\begin{minipage}[t]{\textwidth} \begin{tabular}{ll} {\em $<$pattern$>$ $\longrightarrow$} & {\em Matches:} \\ $<$atom$>$ $\|$ {\tt (kwote { }}$<$atom$>${\tt )} & any expression {\tt eq?} to $<$atom$>$\\ $\|$ {\tt (and} $<$pat$_1>$ \ldots $<$pat$_n>${\tt )} & if all of $<$pat$_i>$ match \\ $\|$ {\tt (or} $<$pat$>$ \ldots $<$pat$_n>${\tt )} & if any of $<$pat$_1>$ through $<$pat$_n> $match \\ $\|$ {\tt (not} $<$pat$>${\tt )} & if $<$pat$>$ doesn't match \\ $\|$ {\tt (?} $<$predicate$>${\tt )} & if $<$predicate$>$ is true\\ $\|$ {\tt ($<$pat$_1>$ \ldots \footnote{Here, \ldots is a meta-character denoting a finite repetition of patterns. } $<$pat$_n>$)} & a list of $n$ elements \\ $\|$ $<$pat$>$ {\tt \underline{\ldots}} \footnote{Here, {\tt \underline{\ldots}} means the special keyword "\ldots". } & a (possibly empty) repetition of $<$pat$>$ in a list. \\ $\|$ {\tt \#($<$pat$>$ \ldots $<$pat$_n>$)} & a vector of n elements \\ $\|$ {\tt ?}$<$identifier$>$ & anything, and binds $identifier$ as a variable \\ $\|$ \verb#?-# & anything \\ $\|$ \verb#??-# & any (possibly empty) repetition of anything in a list \\ $\|$ \verb#???-# & any end of list \\ \end{tabular} %\end{minipage} \end{small} \caption{Pattern Syntax} \label{PatternLanguage} \_\hrulefill\_ \end{table} \begin{note} {\tt and, or, not, check} and {\tt kwote} must be quoted in order to be treated as literals. This is the only justification for having the {\tt kwote} pattern since, by convention, any atom which is not a keyword is quoted. \end{note} \paragraph{Explanations through examples} \begin{itemize} \item {\tt ?-} matches any s-expr \item {\tt a} matches the atom {\tt 'a}. \item {\tt ?a} matches any expression, and binds the variable {\tt a} to this expression. \item {\tt (? integer?)} matches any integer \item {\tt (a (a b))} matches the only list {\tt '(a (a b))}. \item {\tt ???-} can only appear at the end of a list, and always succeeds. For instance, {\tt (a ???-)} is equivalent to {\tt (a . ?-)}. \item when occurring in a list, {\tt ??-} matches any sequence of anything: {\tt (a ??- b)} matches any list whose {\tt car} is {\tt a} and last {\tt car} is {\tt b}. \item \verb#(a ...)# matches any list of {\tt a}'s, possibly empty. \item {\tt (?x ?x)} matches any list of length 2 whose {\tt car} is {\em eq} to its {\tt cadr} \item {\tt ((and (not a) ?x) ?x)} matches any list of length 2 whose {\tt car} is not {\em eq} to {\tt 'a} but is {\em eq} to its {\tt cadr} \item {\tt \#(?- ?- ???-)} matches any vector whose length is at least 2. \end{itemize} \begin{note} {\tt ??-} and \verb#...# patterns can not appear inside a vector, where you should use ???-: For example, {\tt \#(a ??- b)} or {\tt \#(a...)} are invalid patterns, whereas {\tt \#(a ???-)} is valid and matches any vector whose first element is the atom {\tt a}. \end{note} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%% %%%% Section 6.21: 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} %%% Local Variables: %%% mode: latex %%% TeX-master: "manual" %%% End: