diff options
Diffstat (limited to 'slib_3.html')
-rw-r--r-- | slib_3.html | 2013 |
1 files changed, 2013 insertions, 0 deletions
diff --git a/slib_3.html b/slib_3.html new file mode 100644 index 0000000..0f0e6e9 --- /dev/null +++ b/slib_3.html @@ -0,0 +1,2013 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" + "http://www.w3.org/TR/html40/loose.dtd"> +<HTML> +<!-- Created on January, 10 2005 by texi2html 1.66 --> +<!-- +Written by: Lionel Cons <Lionel.Cons@cern.ch> (original author) + Karl Berry <karl@freefriends.org> + Olaf Bachmann <obachman@mathematik.uni-kl.de> + and many others. +Maintained by: Many creative people <dev@texi2html.cvshome.org> +Send bugs and suggestions to <users@texi2html.cvshome.org> + +--> +<HEAD> +<TITLE>SLIB: Scheme Syntax Extension Packages</TITLE> + +<META NAME="description" CONTENT="SLIB: Scheme Syntax Extension Packages"> +<META NAME="keywords" CONTENT="SLIB: Scheme Syntax Extension Packages"> +<META NAME="resource-type" CONTENT="document"> +<META NAME="distribution" CONTENT="global"> +<META NAME="Generator" CONTENT="texi2html 1.66"> + +</HEAD> + +<BODY LANG="en" BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#800080" ALINK="#FF0000"> + +<A NAME="SEC21"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_2.html#SEC20"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC22"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_2.html#SEC13"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_4.html#SEC45"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H1> 3. Scheme Syntax Extension Packages </H1> +<!--docid::SEC21::--> +<P> + +<TABLE BORDER="0" CELLSPACING="0"> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_3.html#SEC22">3.1 Defmacro</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP">Supported by all implementations</TD></TR> +<TR><TH COLSPAN="3" ALIGN="left" VALIGN="TOP"> +</TH></TR> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_3.html#SEC24">3.2 R4RS Macros</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP">'macro</TD></TR> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_3.html#SEC25">3.3 Macro by Example</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP">'macro-by-example</TD></TR> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_3.html#SEC27">3.4 Macros That Work</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP">'macros-that-work</TD></TR> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_3.html#SEC30">3.5 Syntactic Closures</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP">'syntactic-closures</TD></TR> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_3.html#SEC36">3.6 Syntax-Case Macros</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP">'syntax-case</TD></TR> +<TR><TH COLSPAN="3" ALIGN="left" VALIGN="TOP"> +</TH></TR> +<TR><TH COLSPAN="3" ALIGN="left" VALIGN="TOP">Syntax extensions (macros) included with SLIB. +</TH></TR> +<TR><TH COLSPAN="3" ALIGN="left" VALIGN="TOP"> +</TH></TR> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_3.html#SEC39">3.7 Fluid-Let</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP">'fluid-let</TD></TR> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_3.html#SEC40">3.8 Yasos</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP">'yasos, 'oop, 'collect</TD></TR> +</TABLE> +<P> + +<A NAME="Defmacro"></A> +<HR SIZE="6"> +<A NAME="SEC22"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC23"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_4.html#SEC45"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H2> 3.1 Defmacro </H2> +<!--docid::SEC22::--> +<P> + +Defmacros are supported by all implementations. +</P> +<P> + +<A NAME="IDX107"></A> +</P> +<DL> +<DT><U>Function:</U> <B>gentemp</B> +<DD>Returns a new (interned) symbol each time it is called. The symbol +names are implementation-dependent +<TABLE><tr><td> </td><td class=example><pre>(gentemp) => scm:G0 +(gentemp) => scm:G1 +</pre></td></tr></table></DL> +<P> + +<A NAME="IDX108"></A> +</P> +<DL> +<DT><U>Function:</U> <B>defmacro:eval</B> <I>e</I> +<DD>Returns the <CODE>slib:eval</CODE> of expanding all defmacros in scheme +expression <VAR>e</VAR>. +</DL> +<P> + +<A NAME="IDX109"></A> +</P> +<DL> +<DT><U>Function:</U> <B>defmacro:load</B> <I>filename</I> +<DD><VAR>filename</VAR> should be a string. If filename names an existing file, +the <CODE>defmacro:load</CODE> procedure reads Scheme source code expressions +and definitions from the file and evaluates them sequentially. These +source code expressions and definitions may contain defmacro +definitions. The <CODE>macro:load</CODE> procedure does not affect the values +returned by <CODE>current-input-port</CODE> and +<CODE>current-output-port</CODE>. +</DL> +<P> + +<A NAME="IDX110"></A> +</P> +<DL> +<DT><U>Function:</U> <B>defmacro?</B> <I>sym</I> +<DD>Returns <CODE>#t</CODE> if <VAR>sym</VAR> has been defined by <CODE>defmacro</CODE>, +<CODE>#f</CODE> otherwise. +</DL> +<P> + +<A NAME="IDX111"></A> +</P> +<DL> +<DT><U>Function:</U> <B>macroexpand-1</B> <I>form</I> +<DD><A NAME="IDX112"></A> +<DT><U>Function:</U> <B>macroexpand</B> <I>form</I> +<DD>If <VAR>form</VAR> is a macro call, <CODE>macroexpand-1</CODE> will expand the +macro call once and return it. A <VAR>form</VAR> is considered to be a macro +call only if it is a cons whose <CODE>car</CODE> is a symbol for which a +<CODE>defmacro</CODE> has been defined. +<P> + +<CODE>macroexpand</CODE> is similar to <CODE>macroexpand-1</CODE>, but repeatedly +expands <VAR>form</VAR> until it is no longer a macro call. +</P> +</DL> +<P> + +<A NAME="IDX113"></A> +</P> +<DL> +<DT><U>Macro:</U> <B>defmacro</B> <I>name lambda-list form <small>...</small></I> +<DD>When encountered by <CODE>defmacro:eval</CODE>, <CODE>defmacro:macroexpand*</CODE>, +or <CODE>defmacro:load</CODE> defines a new macro which will henceforth be +expanded when encountered by <CODE>defmacro:eval</CODE>, +<CODE>defmacro:macroexpand*</CODE>, or <CODE>defmacro:load</CODE>. +</DL> +<P> + +<HR SIZE="6"> +<A NAME="SEC23"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC22"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC24"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_4.html#SEC45"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H3> 3.1.1 Defmacroexpand </H3> +<!--docid::SEC23::--> +<CODE>(require 'defmacroexpand)</CODE> +<A NAME="IDX114"></A> +<P> + +<A NAME="IDX115"></A> +</P> +<DL> +<DT><U>Function:</U> <B>defmacro:expand*</B> <I>e</I> +<DD>Returns the result of expanding all defmacros in scheme expression +<VAR>e</VAR>. +</DL> +<P> + +<A NAME="R4RS Macros"></A> +<HR SIZE="6"> +<A NAME="SEC24"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC23"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC25"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_4.html#SEC45"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H2> 3.2 R4RS Macros </H2> +<!--docid::SEC24::--> +<P> + +<CODE>(require 'macro)</CODE> is the appropriate call if you want R4RS +<A NAME="IDX116"></A> +high-level macros but don't care about the low level implementation. If +an SLIB R4RS macro implementation is already loaded it will be used. +Otherwise, one of the R4RS macros implemetations is loaded. +</P> +<P> + +The SLIB R4RS macro implementations support the following uniform +interface: +</P> +<P> + +<A NAME="IDX117"></A> +</P> +<DL> +<DT><U>Function:</U> <B>macro:expand</B> <I>sexpression</I> +<DD>Takes an R4RS expression, macro-expands it, and returns the result of +the macro expansion. +</DL> +<P> + +<A NAME="IDX118"></A> +</P> +<DL> +<DT><U>Function:</U> <B>macro:eval</B> <I>sexpression</I> +<DD>Takes an R4RS expression, macro-expands it, evals the result of the +macro expansion, and returns the result of the evaluation. +</DL> +<P> + +<A NAME="IDX119"></A> +</P> +<DL> +<DT><U>Procedure:</U> <B>macro:load</B> <I>filename</I> +<DD><VAR>filename</VAR> should be a string. If filename names an existing file, +the <CODE>macro:load</CODE> procedure reads Scheme source code expressions and +definitions from the file and evaluates them sequentially. These source +code expressions and definitions may contain macro definitions. The +<CODE>macro:load</CODE> procedure does not affect the values returned by +<CODE>current-input-port</CODE> and <CODE>current-output-port</CODE>. +</DL> +<P> + +<A NAME="Macro by Example"></A> +<HR SIZE="6"> +<A NAME="SEC25"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC24"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC26"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_4.html#SEC45"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H2> 3.3 Macro by Example </H2> +<!--docid::SEC25::--> +<P> + +<CODE>(require 'macro-by-example)</CODE> +<A NAME="IDX120"></A> +</P> +<P> + +A vanilla implementation of <CITE>Macro by Example</CITE> (Eugene Kohlbecker, +R4RS) by Dorai Sitaram, (dorai @ cs.rice.edu) using <CODE>defmacro</CODE>. +</P> +<P> + +<UL> + +<LI> +generating hygienic global <CODE>define-syntax</CODE> Macro-by-Example macros +<STRONG>cheaply</STRONG>. +<P> + +</P> +<LI> +can define macros which use <CODE>...</CODE>. +<P> + +</P> +<LI> +needn't worry about a lexical variable in a macro definition +clashing with a variable from the macro use context +<P> + +</P> +<LI> +don't suffer the overhead of redefining the repl if <CODE>defmacro</CODE> +natively supported (most implementations) +<P> + +</UL> +<HR SIZE="6"> +<A NAME="SEC26"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC25"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC27"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_4.html#SEC45"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H3> 3.3.1 Caveat </H3> +<!--docid::SEC26::--> +These macros are not referentially transparent (see section `Macros' in <CITE>Revised(4) Scheme</CITE>). Lexically scoped macros (i.e., <CODE>let-syntax</CODE> +and <CODE>letrec-syntax</CODE>) are not supported. In any case, the problem +of referential transparency gains poignancy only when <CODE>let-syntax</CODE> +and <CODE>letrec-syntax</CODE> are used. So you will not be courting +large-scale disaster unless you're using system-function names as local +variables with unintuitive bindings that the macro can't use. However, +if you must have the full <CITE>r4rs</CITE> macro functionality, look to the +more featureful (but also more expensive) versions of syntax-rules +available in slib <A HREF="slib_3.html#SEC27">3.4 Macros That Work</A>, <A HREF="slib_3.html#SEC30">3.5 Syntactic Closures</A>, and +<A HREF="slib_3.html#SEC36">3.6 Syntax-Case Macros</A>. +<P> + +<A NAME="IDX121"></A> +</P> +<DL> +<DT><U>Macro:</U> <B>define-syntax</B> <I>keyword transformer-spec</I> +<DD>The <VAR>keyword</VAR> is an identifier, and the <VAR>transformer-spec</VAR> +should be an instance of <CODE>syntax-rules</CODE>. +<P> + +The top-level syntactic environment is extended by binding the +<VAR>keyword</VAR> to the specified transformer. +</P> +<P> + +<TABLE><tr><td> </td><td class=example><pre>(define-syntax let* + (syntax-rules () + ((let* () body1 body2 ...) + (let () body1 body2 ...)) + ((let* ((name1 val1) (name2 val2) ...) + body1 body2 ...) + (let ((name1 val1)) + (let* (( name2 val2) ...) + body1 body2 ...))))) +</pre></td></tr></table></DL> +<P> + +<A NAME="IDX122"></A> +</P> +<DL> +<DT><U>Macro:</U> <B>syntax-rules</B> <I>literals syntax-rule <small>...</small></I> +<DD><VAR>literals</VAR> is a list of identifiers, and each <VAR>syntax-rule</VAR> +should be of the form +<P> + +<CODE>(<VAR>pattern</VAR> <VAR>template</VAR>)</CODE> +</P> +<P> + +where the <VAR>pattern</VAR> and <VAR>template</VAR> are as in the grammar above. +</P> +<P> + +An instance of <CODE>syntax-rules</CODE> produces a new macro transformer by +specifying a sequence of hygienic rewrite rules. A use of a macro whose +keyword is associated with a transformer specified by +<CODE>syntax-rules</CODE> is matched against the patterns contained in the +<VAR>syntax-rule</VAR>s, beginning with the leftmost <VAR>syntax-rule</VAR>. +When a match is found, the macro use is trancribed hygienically +according to the template. +</P> +<P> + +Each pattern begins with the keyword for the macro. This keyword is not +involved in the matching and is not considered a pattern variable or +literal identifier. +</P> +</DL> +<P> + +<A NAME="Macros That Work"></A> +<HR SIZE="6"> +<A NAME="SEC27"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC26"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC28"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_4.html#SEC45"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H2> 3.4 Macros That Work </H2> +<!--docid::SEC27::--> +<P> + +<CODE>(require 'macros-that-work)</CODE> +<A NAME="IDX123"></A> +</P> +<P> + +<CITE>Macros That Work</CITE> differs from the other R4RS macro +implementations in that it does not expand derived expression types to +primitive expression types. +</P> +<P> + +<A NAME="IDX124"></A> +</P> +<DL> +<DT><U>Function:</U> <B>macro:expand</B> <I>expression</I> +<DD><A NAME="IDX125"></A> +<DT><U>Function:</U> <B>macwork:expand</B> <I>expression</I> +<DD>Takes an R4RS expression, macro-expands it, and returns the result of +the macro expansion. +</DL> +<P> + +<A NAME="IDX126"></A> +</P> +<DL> +<DT><U>Function:</U> <B>macro:eval</B> <I>expression</I> +<DD><A NAME="IDX127"></A> +<DT><U>Function:</U> <B>macwork:eval</B> <I>expression</I> +<DD><CODE>macro:eval</CODE> returns the value of <VAR>expression</VAR> in the current +top level environment. <VAR>expression</VAR> can contain macro definitions. +Side effects of <VAR>expression</VAR> will affect the top level +environment. +</DL> +<P> + +<A NAME="IDX128"></A> +</P> +<DL> +<DT><U>Procedure:</U> <B>macro:load</B> <I>filename</I> +<DD><A NAME="IDX129"></A> +<DT><U>Procedure:</U> <B>macwork:load</B> <I>filename</I> +<DD><VAR>filename</VAR> should be a string. If filename names an existing file, +the <CODE>macro:load</CODE> procedure reads Scheme source code expressions and +definitions from the file and evaluates them sequentially. These source +code expressions and definitions may contain macro definitions. The +<CODE>macro:load</CODE> procedure does not affect the values returned by +<CODE>current-input-port</CODE> and <CODE>current-output-port</CODE>. +</DL> +<P> + +References: +</P> +<P> + +The <CITE>Revised^4 Report on the Algorithmic Language Scheme</CITE> Clinger +and Rees [editors]. To appear in LISP Pointers. Also available as a +technical report from the University of Oregon, MIT AI Lab, and +Cornell. +</P> +<P> + +<center> + Macros That Work. Clinger and Rees. POPL '91. +</center> +</P> +<P> + +The supported syntax differs from the R4RS in that vectors are allowed +as patterns and as templates and are not allowed as pattern or template +data. +</P> +<P> + +<TABLE><tr><td> </td><td class=example><pre>transformer spec ==> (syntax-rules literals rules) + +rules ==> () + | (rule . rules) + +rule ==> (pattern template) + +pattern ==> pattern_var ; a symbol not in literals + | symbol ; a symbol in literals + | () + | (pattern . pattern) + | (ellipsis_pattern) + | #(pattern*) ; extends R4RS + | #(pattern* ellipsis_pattern) ; extends R4RS + | pattern_datum + +template ==> pattern_var + | symbol + | () + | (template2 . template2) + | #(template*) ; extends R4RS + | pattern_datum + +template2 ==> template + | ellipsis_template + +pattern_datum ==> string ; no vector + | character + | boolean + | number + +ellipsis_pattern ==> pattern ... + +ellipsis_template ==> template ... + +pattern_var ==> symbol ; not in literals + +literals ==> () + | (symbol . literals) +</pre></td></tr></table><P> + +<HR SIZE="6"> +<A NAME="SEC28"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC27"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC29"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_4.html#SEC45"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H3> 3.4.1 Definitions </H3> +<!--docid::SEC28::--> +<P> + +</P> +<DL COMPACT> + +<DT>Scope of an ellipsis +<DD>Within a pattern or template, the scope of an ellipsis (<CODE>...</CODE>) is +the pattern or template that appears to its left. +<P> + +</P> +<DT>Rank of a pattern variable +<DD>The rank of a pattern variable is the number of ellipses within whose +scope it appears in the pattern. +<P> + +</P> +<DT>Rank of a subtemplate +<DD>The rank of a subtemplate is the number of ellipses within whose scope +it appears in the template. +<P> + +</P> +<DT>Template rank of an occurrence of a pattern variable +<DD>The template rank of an occurrence of a pattern variable within a +template is the rank of that occurrence, viewed as a subtemplate. +<P> + +</P> +<DT>Variables bound by a pattern +<DD>The variables bound by a pattern are the pattern variables that appear +within it. +<P> + +</P> +<DT>Referenced variables of a subtemplate +<DD>The referenced variables of a subtemplate are the pattern variables that +appear within it. +<P> + +</P> +<DT>Variables opened by an ellipsis template +<DD>The variables opened by an ellipsis template are the referenced pattern +variables whose rank is greater than the rank of the ellipsis template. +<P> + +</DL> +<P> + +<HR SIZE="6"> +<A NAME="SEC29"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC28"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC30"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_4.html#SEC45"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H3> 3.4.2 Restrictions </H3> +<!--docid::SEC29::--> +<P> + +No pattern variable appears more than once within a pattern. +</P> +<P> + +For every occurrence of a pattern variable within a template, the +template rank of the occurrence must be greater than or equal to the +pattern variable's rank. +</P> +<P> + +Every ellipsis template must open at least one variable. +</P> +<P> + +For every ellipsis template, the variables opened by an ellipsis +template must all be bound to sequences of the same length. +</P> +<P> + +The compiled form of a <VAR>rule</VAR> is +</P> +<P> + +<TABLE><tr><td> </td><td class=example><pre>rule ==> (pattern template inserted) + +pattern ==> pattern_var + | symbol + | () + | (pattern . pattern) + | ellipsis_pattern + | #(pattern) + | pattern_datum + +template ==> pattern_var + | symbol + | () + | (template2 . template2) + | #(pattern) + | pattern_datum + +template2 ==> template + | ellipsis_template + +pattern_datum ==> string + | character + | boolean + | number + +pattern_var ==> #(V symbol rank) + +ellipsis_pattern ==> #(E pattern pattern_vars) + +ellipsis_template ==> #(E template pattern_vars) + +inserted ==> () + | (symbol . inserted) + +pattern_vars ==> () + | (pattern_var . pattern_vars) + +rank ==> exact non-negative integer +</pre></td></tr></table><P> + +where V and E are unforgeable values. +</P> +<P> + +The pattern variables associated with an ellipsis pattern are the +variables bound by the pattern, and the pattern variables associated +with an ellipsis template are the variables opened by the ellipsis +template. +</P> +<P> + +If the template contains a big chunk that contains no pattern variables +or inserted identifiers, then the big chunk will be copied +unnecessarily. That shouldn't matter very often. +</P> +<P> + +<A NAME="Syntactic Closures"></A> +<HR SIZE="6"> +<A NAME="SEC30"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC29"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC31"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_4.html#SEC45"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H2> 3.5 Syntactic Closures </H2> +<!--docid::SEC30::--> +<P> + +<CODE>(require 'syntactic-closures)</CODE> +<A NAME="IDX130"></A> +</P> +<P> + +<A NAME="IDX131"></A> +</P> +<DL> +<DT><U>Function:</U> <B>macro:expand</B> <I>expression</I> +<DD><A NAME="IDX132"></A> +<DT><U>Function:</U> <B>synclo:expand</B> <I>expression</I> +<DD>Returns scheme code with the macros and derived expression types of +<VAR>expression</VAR> expanded to primitive expression types. +</DL> +<P> + +<A NAME="IDX133"></A> +</P> +<DL> +<DT><U>Function:</U> <B>macro:eval</B> <I>expression</I> +<DD><A NAME="IDX134"></A> +<DT><U>Function:</U> <B>synclo:eval</B> <I>expression</I> +<DD><CODE>macro:eval</CODE> returns the value of <VAR>expression</VAR> in the current +top level environment. <VAR>expression</VAR> can contain macro definitions. +Side effects of <VAR>expression</VAR> will affect the top level +environment. +</DL> +<P> + +<A NAME="IDX135"></A> +</P> +<DL> +<DT><U>Procedure:</U> <B>macro:load</B> <I>filename</I> +<DD><A NAME="IDX136"></A> +<DT><U>Procedure:</U> <B>synclo:load</B> <I>filename</I> +<DD><VAR>filename</VAR> should be a string. If filename names an existing file, +the <CODE>macro:load</CODE> procedure reads Scheme source code expressions and +definitions from the file and evaluates them sequentially. These +source code expressions and definitions may contain macro definitions. +The <CODE>macro:load</CODE> procedure does not affect the values returned by +<CODE>current-input-port</CODE> and <CODE>current-output-port</CODE>. +</DL> +<P> + +<HR SIZE="6"> +<A NAME="SEC31"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC30"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC32"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_4.html#SEC45"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H3> 3.5.1 Syntactic Closure Macro Facility </H3> +<!--docid::SEC31::--> +<P> + +<center> + A Syntactic Closures Macro Facility +</center> +<center> + by Chris Hanson +</center> +<center> + 9 November 1991 +</center> +</P> +<P> + +This document describes <EM>syntactic closures</EM>, a low-level macro +facility for the Scheme programming language. The facility is an +alternative to the low-level macro facility described in the +<CITE>Revised^4 Report on Scheme.</CITE> This document is an addendum to that +report. +</P> +<P> + +The syntactic closures facility extends the BNF rule for +<VAR>transformer spec</VAR> to allow a new keyword that introduces a +low-level macro transformer: +</P> +<P> + +<TABLE><tr><td> </td><td class=example><pre><VAR>transformer spec</VAR> := (transformer <VAR>expression</VAR>) +</pre></td></tr></table><P> + +Additionally, the following procedures are added: +<TABLE><tr><td> </td><td class=example><pre>make-syntactic-closure +capture-syntactic-environment +identifier? +identifier=? +</pre></td></tr></table><P> + +The description of the facility is divided into three parts. The first +part defines basic terminology. The second part describes how macro +transformers are defined. The third part describes the use of +<EM>identifiers</EM>, which extend the syntactic closure mechanism to be +compatible with <CODE>syntax-rules</CODE>. +</P> +<P> + +<HR SIZE="6"> +<A NAME="SEC32"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC31"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC33"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_4.html#SEC45"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H4> 3.5.1.1 Terminology </H4> +<!--docid::SEC32::--> +<P> + +This section defines the concepts and data types used by the syntactic +closures facility. +</P> +<P> + +<UL> + +<LI><EM>Forms</EM> are the syntactic entities out of which programs are +recursively constructed. A form is any expression, any definition, any +syntactic keyword, or any syntactic closure. The variable name that +appears in a <CODE>set!</CODE> special form is also a form. Examples of +forms: +<P> + +<TABLE><tr><td> </td><td class=example><pre>17 +#t +car +(+ x 4) +(lambda (x) x) +(define pi 3.14159) +if +define +</pre></td></tr></table><P> + +</P> +<LI>An <EM>alias</EM> is an alternate name for a given symbol. It can +appear anywhere in a form that the symbol could be used, and when quoted +it is replaced by the symbol; however, it does not satisfy the predicate +<CODE>symbol?</CODE>. Macro transformers rarely distinguish symbols from +aliases, referring to both as identifiers. +<P> + +</P> +<LI>A <EM>syntactic</EM> environment maps identifiers to their +meanings. More precisely, it determines whether an identifier is a +syntactic keyword or a variable. If it is a keyword, the meaning is an +interpretation for the form in which that keyword appears. If it is a +variable, the meaning identifies which binding of that variable is +referenced. In short, syntactic environments contain all of the +contextual information necessary for interpreting the meaning of a +particular form. +<P> + +</P> +<LI>A <EM>syntactic closure</EM> consists of a form, a syntactic +environment, and a list of identifiers. All identifiers in the form +take their meaning from the syntactic environment, except those in the +given list. The identifiers in the list are to have their meanings +determined later. A syntactic closure may be used in any context in +which its form could have been used. Since a syntactic closure is also +a form, it may not be used in contexts where a form would be illegal. +For example, a form may not appear as a clause in the cond special form. +A syntactic closure appearing in a quoted structure is replaced by its +form. +<P> + +</UL> +<P> + +<HR SIZE="6"> +<A NAME="SEC33"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC32"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC34"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_4.html#SEC45"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H4> 3.5.1.2 Transformer Definition </H4> +<!--docid::SEC33::--> +<P> + +This section describes the <CODE>transformer</CODE> special form and the +procedures <CODE>make-syntactic-closure</CODE> and +<CODE>capture-syntactic-environment</CODE>. +</P> +<P> + +<A NAME="IDX137"></A> +</P> +<DL> +<DT><U>Syntax:</U> <B>transformer</B> <I>expression</I> +<DD><P> + +Syntax: It is an error if this syntax occurs except as a +<VAR>transformer spec</VAR>. +</P> +<P> + +Semantics: The <VAR>expression</VAR> is evaluated in the standard transformer +environment to yield a macro transformer as described below. This macro +transformer is bound to a macro keyword by the special form in which the +<CODE>transformer</CODE> expression appears (for example, +<CODE>let-syntax</CODE>). +</P> +<P> + +A <EM>macro transformer</EM> is a procedure that takes two arguments, a +form and a syntactic environment, and returns a new form. The first +argument, the <EM>input form</EM>, is the form in which the macro keyword +occurred. The second argument, the <EM>usage environment</EM>, is the +syntactic environment in which the input form occurred. The result of +the transformer, the <EM>output form</EM>, is automatically closed in the +<EM>transformer environment</EM>, which is the syntactic environment in +which the <CODE>transformer</CODE> expression occurred. +</P> +<P> + +For example, here is a definition of a push macro using +<CODE>syntax-rules</CODE>: +</P> +<P> + +<TABLE><tr><td> </td><td class=example><pre>(define-syntax push + (syntax-rules () + ((push item list) + (set! list (cons item list))))) +</pre></td></tr></table><P> + +Here is an equivalent definition using <CODE>transformer</CODE>: +<TABLE><tr><td> </td><td class=example><pre>(define-syntax push + (transformer + (lambda (exp env) + (let ((item + (make-syntactic-closure env '() (cadr exp))) + (list + (make-syntactic-closure env '() (caddr exp)))) + `(set! ,list (cons ,item ,list)))))) +</pre></td></tr></table><P> + +In this example, the identifiers <CODE>set!</CODE> and <CODE>cons</CODE> are closed +in the transformer environment, and thus will not be affected by the +meanings of those identifiers in the usage environment +<CODE>env</CODE>. +</P> +<P> + +Some macros may be non-hygienic by design. For example, the following +defines a loop macro that implicitly binds <CODE>exit</CODE> to an escape +procedure. The binding of <CODE>exit</CODE> is intended to capture free +references to <CODE>exit</CODE> in the body of the loop, so <CODE>exit</CODE> must +be left free when the body is closed: +</P> +<P> + +<TABLE><tr><td> </td><td class=example><pre>(define-syntax loop + (transformer + (lambda (exp env) + (let ((body (cdr exp))) + `(call-with-current-continuation + (lambda (exit) + (let f () + ,@(map (lambda (exp) + (make-syntactic-closure env '(exit) + exp)) + body) + (f)))))))) +</pre></td></tr></table><P> + +To assign meanings to the identifiers in a form, use +<CODE>make-syntactic-closure</CODE> to close the form in a syntactic +environment. +</P> +</DL> +<P> + +<A NAME="IDX138"></A> +</P> +<DL> +<DT><U>Function:</U> <B>make-syntactic-closure</B> <I>environment free-names form</I> +<DD><P> + +<VAR>environment</VAR> must be a syntactic environment, <VAR>free-names</VAR> must +be a list of identifiers, and <VAR>form</VAR> must be a form. +<CODE>make-syntactic-closure</CODE> constructs and returns a syntactic closure +of <VAR>form</VAR> in <VAR>environment</VAR>, which can be used anywhere that +<VAR>form</VAR> could have been used. All the identifiers used in +<VAR>form</VAR>, except those explicitly excepted by <VAR>free-names</VAR>, obtain +their meanings from <VAR>environment</VAR>. +</P> +<P> + +Here is an example where <VAR>free-names</VAR> is something other than the +empty list. It is instructive to compare the use of <VAR>free-names</VAR> in +this example with its use in the <CODE>loop</CODE> example above: the examples +are similar except for the source of the identifier being left +free. +<TABLE><tr><td> </td><td class=example><pre>(define-syntax let1 + (transformer + (lambda (exp env) + (let ((id (cadr exp)) + (init (caddr exp)) + (exp (cadddr exp))) + `((lambda (,id) + ,(make-syntactic-closure env (list id) exp)) + ,(make-syntactic-closure env '() init)))))) +</pre></td></tr></table><P> + +<CODE>let1</CODE> is a simplified version of <CODE>let</CODE> that only binds a +single identifier, and whose body consists of a single expression. When +the body expression is syntactically closed in its original syntactic +environment, the identifier that is to be bound by <CODE>let1</CODE> must be +left free, so that it can be properly captured by the <CODE>lambda</CODE> in +the output form. +</P> +<P> + +To obtain a syntactic environment other than the usage environment, use +<CODE>capture-syntactic-environment</CODE>. +</P> +</DL> +<P> + +<A NAME="IDX139"></A> +</P> +<DL> +<DT><U>Function:</U> <B>capture-syntactic-environment</B> <I>procedure</I> +<DD><P> + +<CODE>capture-syntactic-environment</CODE> returns a form that will, when +transformed, call <VAR>procedure</VAR> on the current syntactic environment. +<VAR>procedure</VAR> should compute and return a new form to be transformed, +in that same syntactic environment, in place of the form. +</P> +<P> + +An example will make this clear. Suppose we wanted to define a simple +<CODE>loop-until</CODE> keyword equivalent to +</P> +<P> + +<TABLE><tr><td> </td><td class=example><pre>(define-syntax loop-until + (syntax-rules () + ((loop-until id init test return step) + (letrec ((loop + (lambda (id) + (if test return (loop step))))) + (loop init))))) +</pre></td></tr></table><P> + +The following attempt at defining <CODE>loop-until</CODE> has a subtle bug: +<TABLE><tr><td> </td><td class=example><pre>(define-syntax loop-until + (transformer + (lambda (exp env) + (let ((id (cadr exp)) + (init (caddr exp)) + (test (cadddr exp)) + (return (cadddr (cdr exp))) + (step (cadddr (cddr exp))) + (close + (lambda (exp free) + (make-syntactic-closure env free exp)))) + `(letrec ((loop + (lambda (,id) + (if ,(close test (list id)) + ,(close return (list id)) + (loop ,(close step (list id))))))) + (loop ,(close init '()))))))) +</pre></td></tr></table><P> + +This definition appears to take all of the proper precautions to prevent +unintended captures. It carefully closes the subexpressions in their +original syntactic environment and it leaves the <CODE>id</CODE> identifier +free in the <CODE>test</CODE>, <CODE>return</CODE>, and <CODE>step</CODE> expressions, so +that it will be captured by the binding introduced by the <CODE>lambda</CODE> +expression. Unfortunately it uses the identifiers <CODE>if</CODE> and +<CODE>loop</CODE> within that <CODE>lambda</CODE> expression, so if the user of +<CODE>loop-until</CODE> just happens to use, say, <CODE>if</CODE> for the +identifier, it will be inadvertently captured. +</P> +<P> + +The syntactic environment that <CODE>if</CODE> and <CODE>loop</CODE> want to be +exposed to is the one just outside the <CODE>lambda</CODE> expression: before +the user's identifier is added to the syntactic environment, but after +the identifier loop has been added. +<CODE>capture-syntactic-environment</CODE> captures exactly that environment +as follows: +</P> +<P> + +<TABLE><tr><td> </td><td class=example><pre>(define-syntax loop-until + (transformer + (lambda (exp env) + (let ((id (cadr exp)) + (init (caddr exp)) + (test (cadddr exp)) + (return (cadddr (cdr exp))) + (step (cadddr (cddr exp))) + (close + (lambda (exp free) + (make-syntactic-closure env free exp)))) + `(letrec ((loop + ,(capture-syntactic-environment + (lambda (env) + `(lambda (,id) + (,(make-syntactic-closure env '() `if) + ,(close test (list id)) + ,(close return (list id)) + (,(make-syntactic-closure env '() + `loop) + ,(close step (list id))))))))) + (loop ,(close init '()))))))) +</pre></td></tr></table><P> + +In this case, having captured the desired syntactic environment, it is +convenient to construct syntactic closures of the identifiers <CODE>if</CODE> +and the <CODE>loop</CODE> and use them in the body of the +<CODE>lambda</CODE>. +</P> +<P> + +A common use of <CODE>capture-syntactic-environment</CODE> is to get the +transformer environment of a macro transformer: +</P> +<P> + +<TABLE><tr><td> </td><td class=example><pre>(transformer + (lambda (exp env) + (capture-syntactic-environment + (lambda (transformer-env) + ...)))) +</pre></td></tr></table></DL> +<P> + +<HR SIZE="6"> +<A NAME="SEC34"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC33"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC35"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_4.html#SEC45"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H4> 3.5.1.3 Identifiers </H4> +<!--docid::SEC34::--> +<P> + +This section describes the procedures that create and manipulate +identifiers. Previous syntactic closure proposals did not have an +identifier data type -- they just used symbols. The identifier data +type extends the syntactic closures facility to be compatible with the +high-level <CODE>syntax-rules</CODE> facility. +</P> +<P> + +As discussed earlier, an identifier is either a symbol or an +<EM>alias</EM>. An alias is implemented as a syntactic closure whose +<EM>form</EM> is an identifier: +</P> +<P> + +<TABLE><tr><td> </td><td class=example><pre>(make-syntactic-closure env '() 'a) + => an <EM>alias</EM> +</pre></td></tr></table><P> + +Aliases are implemented as syntactic closures because they behave just +like syntactic closures most of the time. The difference is that an +alias may be bound to a new value (for example by <CODE>lambda</CODE> or +<CODE>let-syntax</CODE>); other syntactic closures may not be used this way. +If an alias is bound, then within the scope of that binding it is looked +up in the syntactic environment just like any other identifier. +</P> +<P> + +Aliases are used in the implementation of the high-level facility +<CODE>syntax-rules</CODE>. A macro transformer created by <CODE>syntax-rules</CODE> +uses a template to generate its output form, substituting subforms of +the input form into the template. In a syntactic closures +implementation, all of the symbols in the template are replaced by +aliases closed in the transformer environment, while the output form +itself is closed in the usage environment. This guarantees that the +macro transformation is hygienic, without requiring the transformer to +know the syntactic roles of the substituted input subforms. +</P> +<P> + +<A NAME="IDX140"></A> +</P> +<DL> +<DT><U>Function:</U> <B>identifier?</B> <I>object</I> +<DD>Returns <CODE>#t</CODE> if <VAR>object</VAR> is an identifier, otherwise returns +<CODE>#f</CODE>. Examples: +<P> + +<TABLE><tr><td> </td><td class=example><pre>(identifier? 'a) + => #t +(identifier? (make-syntactic-closure env '() 'a)) + => #t +(identifier? "a") + => #f +(identifier? #\a) + => #f +(identifier? 97) + => #f +(identifier? #f) + => #f +(identifier? '(a)) + => #f +(identifier? '#(a)) + => #f +</pre></td></tr></table><P> + +The predicate <CODE>eq?</CODE> is used to determine if two identifers are +"the same". Thus <CODE>eq?</CODE> can be used to compare identifiers +exactly as it would be used to compare symbols. Often, though, it is +useful to know whether two identifiers "mean the same thing". For +example, the <CODE>cond</CODE> macro uses the symbol <CODE>else</CODE> to identify +the final clause in the conditional. A macro transformer for +<CODE>cond</CODE> cannot just look for the symbol <CODE>else</CODE>, because the +<CODE>cond</CODE> form might be the output of another macro transformer that +replaced the symbol <CODE>else</CODE> with an alias. Instead the transformer +must look for an identifier that "means the same thing" in the usage +environment as the symbol <CODE>else</CODE> means in the transformer +environment. +</P> +</DL> +<P> + +<A NAME="IDX141"></A> +</P> +<DL> +<DT><U>Function:</U> <B>identifier=?</B> <I>environment1 identifier1 environment2 identifier2</I> +<DD><VAR>environment1</VAR> and <VAR>environment2</VAR> must be syntactic +environments, and <VAR>identifier1</VAR> and <VAR>identifier2</VAR> must be +identifiers. <CODE>identifier=?</CODE> returns <CODE>#t</CODE> if the meaning of +<VAR>identifier1</VAR> in <VAR>environment1</VAR> is the same as that of +<VAR>identifier2</VAR> in <VAR>environment2</VAR>, otherwise it returns <CODE>#f</CODE>. +Examples: +<P> + +<TABLE><tr><td> </td><td class=example><pre>(let-syntax + ((foo + (transformer + (lambda (form env) + (capture-syntactic-environment + (lambda (transformer-env) + (identifier=? transformer-env 'x env 'x))))))) + (list (foo) + (let ((x 3)) + (foo)))) + => (#t #f) +</pre></td></tr></table><P> + +<TABLE><tr><td> </td><td class=example><pre>(let-syntax ((bar foo)) + (let-syntax + ((foo + (transformer + (lambda (form env) + (capture-syntactic-environment + (lambda (transformer-env) + (identifier=? transformer-env 'foo + env (cadr form)))))))) + (list (foo foo) + (foobar)))) + => (#f #t) +</pre></td></tr></table></DL> +<P> + +<HR SIZE="6"> +<A NAME="SEC35"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC34"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC36"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_4.html#SEC45"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H4> 3.5.1.4 Acknowledgements </H4> +<!--docid::SEC35::--> +<P> + +The syntactic closures facility was invented by Alan Bawden and Jonathan +Rees. The use of aliases to implement <CODE>syntax-rules</CODE> was invented +by Alan Bawden (who prefers to call them <EM>synthetic names</EM>). Much +of this proposal is derived from an earlier proposal by Alan +Bawden. +</P> +<P> + +<A NAME="Syntax-Case Macros"></A> +<HR SIZE="6"> +<A NAME="SEC36"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC35"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC37"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_4.html#SEC45"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H2> 3.6 Syntax-Case Macros </H2> +<!--docid::SEC36::--> +<P> + +<CODE>(require 'syntax-case)</CODE> +<A NAME="IDX142"></A> +</P> +<P> + +<A NAME="IDX143"></A> +</P> +<DL> +<DT><U>Function:</U> <B>macro:expand</B> <I>expression</I> +<DD><A NAME="IDX144"></A> +<DT><U>Function:</U> <B>syncase:expand</B> <I>expression</I> +<DD>Returns scheme code with the macros and derived expression types of +<VAR>expression</VAR> expanded to primitive expression types. +</DL> +<P> + +<A NAME="IDX145"></A> +</P> +<DL> +<DT><U>Function:</U> <B>macro:eval</B> <I>expression</I> +<DD><A NAME="IDX146"></A> +<DT><U>Function:</U> <B>syncase:eval</B> <I>expression</I> +<DD><CODE>macro:eval</CODE> returns the value of <VAR>expression</VAR> in the current +top level environment. <VAR>expression</VAR> can contain macro definitions. +Side effects of <VAR>expression</VAR> will affect the top level +environment. +</DL> +<P> + +<A NAME="IDX147"></A> +</P> +<DL> +<DT><U>Procedure:</U> <B>macro:load</B> <I>filename</I> +<DD><A NAME="IDX148"></A> +<DT><U>Procedure:</U> <B>syncase:load</B> <I>filename</I> +<DD><VAR>filename</VAR> should be a string. If filename names an existing file, +the <CODE>macro:load</CODE> procedure reads Scheme source code expressions and +definitions from the file and evaluates them sequentially. These +source code expressions and definitions may contain macro definitions. +The <CODE>macro:load</CODE> procedure does not affect the values returned by +<CODE>current-input-port</CODE> and <CODE>current-output-port</CODE>. +</DL> +<P> + +This is version 2.1 of <CODE>syntax-case</CODE>, the low-level macro facility +proposed and implemented by Robert Hieb and R. Kent Dybvig. +</P> +<P> + +This version is further adapted by Harald Hanche-Olsen +<hanche @ imf.unit.no> to make it compatible with, and easily usable +with, SLIB. Mainly, these adaptations consisted of: +</P> +<P> + +<UL> +<LI> +Removing white space from `<TT>expand.pp</TT>' to save space in the +distribution. This file is not meant for human readers anyway<small>...</small> +<P> + +</P> +<LI> +Removed a couple of Chez scheme dependencies. +<P> + +</P> +<LI> +Renamed global variables used to minimize the possibility of name +conflicts. +<P> + +</P> +<LI> +Adding an SLIB-specific initialization file. +<P> + +</P> +<LI> +Removing a couple extra files, most notably the documentation (but see +below). +</UL> +<P> + +If you wish, you can see exactly what changes were done by reading the +shell script in the file `<TT>syncase.sh</TT>'. +</P> +<P> + +The two PostScript files were omitted in order to not burden the SLIB +distribution with them. If you do intend to use <CODE>syntax-case</CODE>, +however, you should get these files and print them out on a PostScript +printer. They are available with the original <CODE>syntax-case</CODE> +distribution by anonymous FTP in +`<TT>cs.indiana.edu:/pub/scheme/syntax-case</TT>'. +</P> +<P> + +In order to use syntax-case from an interactive top level, execute: +<TABLE><tr><td> </td><td class=example><pre>(require 'syntax-case) +<A NAME="IDX149"></A>(require 'repl) +<A NAME="IDX150"></A>(repl:top-level macro:eval) +</pre></td></tr></table>See the section Repl (see section <A HREF="slib_7.html#SEC264">7.5.1 Repl</A>) for more information. +<P> + +To check operation of syntax-case get +`<TT>cs.indiana.edu:/pub/scheme/syntax-case</TT>', and type +<TABLE><tr><td> </td><td class=example><pre>(require 'syntax-case) +<A NAME="IDX151"></A><A NAME="IDX152"></A>(syncase:sanity-check) +</pre></td></tr></table><P> + +Beware that <CODE>syntax-case</CODE> takes a long time to load -- about 20s on +a SPARCstation SLC (with SCM) and about 90s on a Macintosh SE/30 (with +Gambit). +</P> +<P> + +<HR SIZE="6"> +<A NAME="SEC37"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC36"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC38"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_4.html#SEC45"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H3> 3.6.1 Notes </H3> +<!--docid::SEC37::--> +<P> + +All R4RS syntactic forms are defined, including <CODE>delay</CODE>. Along +with <CODE>delay</CODE> are simple definitions for <CODE>make-promise</CODE> (into +which <CODE>delay</CODE> expressions expand) and <CODE>force</CODE>. +</P> +<P> + +<CODE>syntax-rules</CODE> and <CODE>with-syntax</CODE> (described in <CITE>TR356</CITE>) +are defined. +</P> +<P> + +<CODE>syntax-case</CODE> is actually defined as a macro that expands into +calls to the procedure <CODE>syntax-dispatch</CODE> and the core form +<CODE>syntax-lambda</CODE>; do not redefine these names. +</P> +<P> + +Several other top-level bindings not documented in TR356 are created: +<UL> +<LI>the "hooks" in `<TT>hooks.ss</TT>' +<LI>the <CODE>build-</CODE> procedures in `<TT>output.ss</TT>' +<LI><CODE>expand-syntax</CODE> (the expander) +</UL> +<P> + +The syntax of define has been extended to allow <CODE>(define <VAR>id</VAR>)</CODE>, +which assigns <VAR>id</VAR> to some unspecified value. +</P> +<P> + +We have attempted to maintain R4RS compatibility where possible. The +incompatibilities should be confined to `<TT>hooks.ss</TT>'. Please let us +know if there is some incompatibility that is not flagged as such. +</P> +<P> + +Send bug reports, comments, suggestions, and questions to Kent Dybvig +(dyb @ iuvax.cs.indiana.edu). +</P> +<P> + +<HR SIZE="6"> +<A NAME="SEC38"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC37"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC39"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_4.html#SEC45"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H3> 3.6.2 Note from SLIB maintainer </H3> +<!--docid::SEC38::--> +<P> + +<CODE>(require 'structure)</CODE> +</P> +<P> + +<A NAME="IDX153"></A> +Included with the <CODE>syntax-case</CODE> files was `<TT>structure.scm</TT>' +which defines a macro <CODE>define-structure</CODE>. I have no +documentation for this macro; it is not used by any other code in +SLIB. +</P> +<P> + +<A NAME="Fluid-Let"></A> +<HR SIZE="6"> +<A NAME="SEC39"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC38"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC40"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_4.html#SEC45"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H2> 3.7 Fluid-Let </H2> +<!--docid::SEC39::--> +<P> + +<CODE>(require 'fluid-let)</CODE> +<A NAME="IDX154"></A> +</P> +<P> + +<A NAME="IDX155"></A> +</P> +<DL> +<DT><U>Syntax:</U> <B>fluid-let</B> <I><CODE>(<VAR>bindings</VAR> <small>...</small>)</CODE> <VAR>forms</VAR><small>...</small></I> +<DD></DL> +<TABLE><tr><td> </td><td class=example><pre>(fluid-let ((<VAR>variable</VAR> <VAR>init</VAR>) <small>...</small>) + <VAR>expression</VAR> <VAR>expression</VAR> <small>...</small>) +</pre></td></tr></table><P> + +The <VAR>init</VAR>s are evaluated in the current environment (in some +unspecified order), the current values of the <VAR>variable</VAR>s are saved, +the results are assigned to the <VAR>variable</VAR>s, the <VAR>expression</VAR>s +are evaluated sequentially in the current environment, the +<VAR>variable</VAR>s are restored to their original values, and the value of +the last <VAR>expression</VAR> is returned. +</P> +<P> + +The syntax of this special form is similar to that of <CODE>let</CODE>, but +<CODE>fluid-let</CODE> temporarily rebinds existing <VAR>variable</VAR>s. Unlike +<CODE>let</CODE>, <CODE>fluid-let</CODE> creates no new bindings; instead it +<EM>assigns</EM> the values of each <VAR>init</VAR> to the binding (determined +by the rules of lexical scoping) of its corresponding +<VAR>variable</VAR>. +</P> +<P> + +<A NAME="Yasos"></A> +<HR SIZE="6"> +<A NAME="SEC40"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC39"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC41"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_4.html#SEC45"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H2> 3.8 Yasos </H2> +<!--docid::SEC40::--> +<P> + +<CODE>(require 'oop)</CODE> or <CODE>(require 'yasos)</CODE> +<A NAME="IDX156"></A> +<A NAME="IDX157"></A> +</P> +<P> + +`Yet Another Scheme Object System' is a simple object system for Scheme +based on the paper by Norman Adams and Jonathan Rees: <CITE>Object +Oriented Programming in Scheme</CITE>, Proceedings of the 1988 ACM Conference +on LISP and Functional Programming, July 1988 [ACM #552880]. +</P> +<P> + +Another reference is: +</P> +<P> + +Ken Dickey. +<A HREF="ftp://ftp.cs.indiana.edu/pub/scheme-repository/doc/pubs/swob.txt"> +Scheming with Objects +</A> +<CITE>AI Expert</CITE> Volume 7, Number 10 (October 1992), pp. 24-33. +</P> +<P> + +<TABLE BORDER="0" CELLSPACING="0"> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_3.html#SEC41">3.8.1 Terms</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP">Definitions and disclaimer.</TD></TR> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_3.html#SEC42">3.8.2 Interface</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP">The Yasos macros and procedures.</TD></TR> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_3.html#SEC43">3.8.3 Setters</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP">Dylan-like setters in Yasos.</TD></TR> +<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="slib_3.html#SEC44">3.8.4 Examples</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP">Usage of Yasos and setters.</TD></TR> +</TABLE> +<P> + +<A NAME="Yasos terms"></A> +<HR SIZE="6"> +<A NAME="SEC41"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC40"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC42"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC40"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_4.html#SEC45"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H3> 3.8.1 Terms </H3> +<!--docid::SEC41::--> +<P> + +</P> +<DL COMPACT> +<DT><EM>Object</EM> +<DD>Any Scheme data object. +<P> + +</P> +<DT><EM>Instance</EM> +<DD>An instance of the OO system; an <EM>object</EM>. +<P> + +</P> +<DT><EM>Operation</EM> +<DD>A <VAR>method</VAR>. +</DL> +<P> + +</P> +<DL COMPACT> +<DT><EM>Notes:</EM> +<DD>The object system supports multiple inheritance. An instance can +inherit from 0 or more ancestors. In the case of multiple inherited +operations with the same identity, the operation used is that from the +first ancestor which contains it (in the ancestor <CODE>let</CODE>). An +operation may be applied to any Scheme data object--not just instances. +As code which creates instances is just code, there are no <EM>classes</EM> +and no meta-<VAR>anything</VAR>. Method dispatch is by a procedure call a la +CLOS rather than by <CODE>send</CODE> syntax a la Smalltalk. +<P> + +</P> +<DT><EM>Disclaimer:</EM> +<DD>There are a number of optimizations which can be made. This +implementation is expository (although performance should be quite +reasonable). See the L&FP paper for some suggestions. +</DL> +<P> + +<A NAME="Yasos interface"></A> +<HR SIZE="6"> +<A NAME="SEC42"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC41"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC43"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC40"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_4.html#SEC45"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H3> 3.8.2 Interface </H3> +<!--docid::SEC42::--> +<P> + +<A NAME="IDX158"></A> +</P> +<DL> +<DT><U>Syntax:</U> <B>define-operation</B> <I><CODE>(</CODE>opname self arg <small>...</small><CODE>)</CODE> <VAR>default-body</VAR></I> +<DD>Defines a default behavior for data objects which don't handle the +operation <VAR>opname</VAR>. The default behavior (for an empty +<VAR>default-body</VAR>) is to generate an error. +</DL> +<P> + +<A NAME="IDX159"></A> +</P> +<DL> +<DT><U>Syntax:</U> <B>define-predicate</B> <I>opname?</I> +<DD>Defines a predicate <VAR>opname?</VAR>, usually used for determining the +<EM>type</EM> of an object, such that <CODE>(<VAR>opname?</VAR> <VAR>object</VAR>)</CODE> +returns <CODE>#t</CODE> if <VAR>object</VAR> has an operation <VAR>opname?</VAR> and +<CODE>#f</CODE> otherwise. +</DL> +<P> + +<A NAME="IDX160"></A> +</P> +<DL> +<DT><U>Syntax:</U> <B>object</B> <I><CODE>((<VAR>name</VAR> <VAR>self</VAR> <VAR>arg</VAR> <small>...</small>) <VAR>body</VAR>)</CODE> <small>...</small></I> +<DD>Returns an object (an instance of the object system) with operations. +Invoking <CODE>(<VAR>name</VAR> <VAR>object</VAR> <VAR>arg</VAR> <small>...</small></CODE> executes the +<VAR>body</VAR> of the <VAR>object</VAR> with <VAR>self</VAR> bound to <VAR>object</VAR> and +with argument(s) <VAR>arg</VAR><small>...</small>. +</DL> +<P> + +<A NAME="IDX161"></A> +</P> +<DL> +<DT><U>Syntax:</U> <B>object-with-ancestors</B> <I><CODE>((</CODE>ancestor1 init1<CODE>)</CODE> <small>...</small><CODE>)</CODE> operation <small>...</small></I> +<DD>A <CODE>let</CODE>-like form of <CODE>object</CODE> for multiple inheritance. It +returns an object inheriting the behaviour of <VAR>ancestor1</VAR> etc. An +operation will be invoked in an ancestor if the object itself does not +provide such a method. In the case of multiple inherited operations +with the same identity, the operation used is the one found in the first +ancestor in the ancestor list. +</DL> +<P> + +<A NAME="IDX162"></A> +</P> +<DL> +<DT><U>Syntax:</U> <B>operate-as</B> <I>component operation self arg <small>...</small></I> +<DD>Used in an operation definition (of <VAR>self</VAR>) to invoke the +<VAR>operation</VAR> in an ancestor <VAR>component</VAR> but maintain the object's +identity. Also known as "send-to-super". +</DL> +<P> + +<A NAME="IDX163"></A> +</P> +<DL> +<DT><U>Procedure:</U> <B>print</B> <I>obj port</I> +<DD>A default <CODE>print</CODE> operation is provided which is just <CODE>(format +<VAR>port</VAR> <VAR>obj</VAR>)</CODE> (see section <A HREF="slib_4.html#SEC53">4.2 Format (version 3.0)</A>) for non-instances and prints +<VAR>obj</VAR> preceded by `<SAMP>#<INSTANCE></SAMP>' for instances. +</DL> +<P> + +<A NAME="IDX164"></A> +</P> +<DL> +<DT><U>Function:</U> <B>size</B> <I>obj</I> +<DD>The default method returns the number of elements in <VAR>obj</VAR> if it is +a vector, string or list, <CODE>2</CODE> for a pair, <CODE>1</CODE> for a character +and by default id an error otherwise. Objects such as collections +(see section <A HREF="slib_7.html#SEC194">7.1.9 Collections</A>) may override the default in an obvious way. +</DL> +<P> + +<A NAME="Setters"></A> +<HR SIZE="6"> +<A NAME="SEC43"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC42"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC44"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC40"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_4.html#SEC45"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H3> 3.8.3 Setters </H3> +<!--docid::SEC43::--> +<P> + +<EM>Setters</EM> implement <EM>generalized locations</EM> for objects +associated with some sort of mutable state. A <EM>getter</EM> operation +retrieves a value from a generalized location and the corresponding +setter operation stores a value into the location. Only the getter is +named -- the setter is specified by a procedure call as below. (Dylan +uses special syntax.) Typically, but not necessarily, getters are +access operations to extract values from Yasos objects (see section <A HREF="slib_3.html#SEC40">3.8 Yasos</A>). +Several setters are predefined, corresponding to getters <CODE>car</CODE>, +<CODE>cdr</CODE>, <CODE>string-ref</CODE> and <CODE>vector-ref</CODE> e.g., <CODE>(setter +car)</CODE> is equivalent to <CODE>set-car!</CODE>. +</P> +<P> + +This implementation of setters is similar to that in Dylan(TM) +(<CITE>Dylan: An object-oriented dynamic language</CITE>, Apple Computer +Eastern Research and Technology). Common LISP provides similar +facilities through <CODE>setf</CODE>. +</P> +<P> + +<A NAME="IDX165"></A> +</P> +<DL> +<DT><U>Function:</U> <B>setter</B> <I>getter</I> +<DD>Returns the setter for the procedure <VAR>getter</VAR>. E.g., since +<CODE>string-ref</CODE> is the getter corresponding to a setter which is +actually <CODE>string-set!</CODE>: +<TABLE><tr><td> </td><td class=example><pre>(define foo "foo") +((setter string-ref) foo 0 #\F) ; set element 0 of foo +foo => "Foo" +</pre></td></tr></table></DL> +<P> + +<A NAME="IDX166"></A> +</P> +<DL> +<DT><U>Syntax:</U> <B>set</B> <I>place new-value</I> +<DD>If <VAR>place</VAR> is a variable name, <CODE>set</CODE> is equivalent to +<CODE>set!</CODE>. Otherwise, <VAR>place</VAR> must have the form of a procedure +call, where the procedure name refers to a getter and the call indicates +an accessible generalized location, i.e., the call would return a value. +The return value of <CODE>set</CODE> is usually unspecified unless used with a +setter whose definition guarantees to return a useful value. +<TABLE><tr><td> </td><td class=example><pre>(set (string-ref foo 2) #\O) ; generalized location with getter +foo => "FoO" +(set foo "foo") ; like set! +foo => "foo" +</pre></td></tr></table></DL> +<P> + +<A NAME="IDX167"></A> +</P> +<DL> +<DT><U>Procedure:</U> <B>add-setter</B> <I>getter setter</I> +<DD>Add procedures <VAR>getter</VAR> and <VAR>setter</VAR> to the (inaccessible) list +of valid setter/getter pairs. <VAR>setter</VAR> implements the store +operation corresponding to the <VAR>getter</VAR> access operation for the +relevant state. The return value is unspecified. +</DL> +<P> + +<A NAME="IDX168"></A> +</P> +<DL> +<DT><U>Procedure:</U> <B>remove-setter-for</B> <I>getter</I> +<DD>Removes the setter corresponding to the specified <VAR>getter</VAR> from the +list of valid setters. The return value is unspecified. +</DL> +<P> + +<A NAME="IDX169"></A> +</P> +<DL> +<DT><U>Syntax:</U> <B>define-access-operation</B> <I>getter-name</I> +<DD>Shorthand for a Yasos <CODE>define-operation</CODE> defining an operation +<VAR>getter-name</VAR> that objects may support to return the value of some +mutable state. The default operation is to signal an error. The return +value is unspecified. +</DL> +<P> + +<A NAME="Yasos examples"></A> +<HR SIZE="6"> +<A NAME="SEC44"></A> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC43"> < </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_4.html#SEC45"> > </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC40"> Up </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_4.html#SEC45"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<H3> 3.8.4 Examples </H3> +<!--docid::SEC44::--> +<P> + +<TABLE><tr><td> </td><td class=example><pre>;;; These definitions for PRINT and SIZE are +;;; already supplied by +(require 'yasos) + +(define-operation (print obj port) + (format port + (if (instance? obj) "#<instance>" "~s") + obj)) + +(define-operation (size obj) + (cond + ((vector? obj) (vector-length obj)) + ((list? obj) (length obj)) + ((pair? obj) 2) + ((string? obj) (string-length obj)) + ((char? obj) 1) + (else + (slib:error "Operation not supported: size" obj)))) + +(define-predicate cell?) +(define-operation (fetch obj)) +(define-operation (store! obj newValue)) + +(define (make-cell value) + (object + ((cell? self) #t) + ((fetch self) value) + ((store! self newValue) + (set! value newValue) + newValue) + ((size self) 1) + ((print self port) + (format port "#<Cell: ~s>" (fetch self))))) + +(define-operation (discard obj value) + (format #t "Discarding ~s~%" value)) + +(define (make-filtered-cell value filter) + (object-with-ancestors + ((cell (make-cell value))) + ((store! self newValue) + (if (filter newValue) + (store! cell newValue) + (discard self newValue))))) + +(define-predicate array?) +(define-operation (array-ref array index)) +(define-operation (array-set! array index value)) + +(define (make-array num-slots) + (let ((anArray (make-vector num-slots))) + (object + ((array? self) #t) + ((size self) num-slots) + ((array-ref self index) + (vector-ref anArray index)) + ((array-set! self index newValue) + (vector-set! anArray index newValue)) + ((print self port) + (format port "#<Array ~s>" (size self)))))) + +(define-operation (position obj)) +(define-operation (discarded-value obj)) + +(define (make-cell-with-history value filter size) + (let ((pos 0) (most-recent-discard #f)) + (object-with-ancestors + ((cell (make-filtered-call value filter)) + (sequence (make-array size))) + ((array? self) #f) + ((position self) pos) + ((store! self newValue) + (operate-as cell store! self newValue) + (array-set! self pos newValue) + (set! pos (+ pos 1))) + ((discard self value) + (set! most-recent-discard value)) + ((discarded-value self) most-recent-discard) + ((print self port) + (format port "#<Cell-with-history ~s>" + (fetch self)))))) + +(define-access-operation fetch) +(add-setter fetch store!) +(define foo (make-cell 1)) +(print foo #f) +=> "#<Cell: 1>" +(set (fetch foo) 2) +=> +(print foo #f) +=> "#<Cell: 2>" +(fetch foo) +=> 2 +</pre></td></tr></table><P> + +<A NAME="Textual Conversion Packages"></A> +<HR SIZE="6"> +<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0> +<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_3.html#SEC21"> << </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_4.html#SEC45"> >> </A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib.html#SEC_Top">Top</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_toc.html#SEC_Contents">Contents</A>]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD> +<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="slib_abt.html#SEC_About"> ? </A>]</TD> +</TR></TABLE> +<BR> +<FONT SIZE="-1"> +This document was generated +by <I>Steve Langasek</I> on <I>January, 10 2005</I> +using <A HREF="http://texi2html.cvshome.org"><I>texi2html</I></A> +</FONT> + +</BODY> +</HTML> |