[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
guile/guile-core/doc ChangeLog scheme-data.texi...
From: |
Neil Jerram |
Subject: |
guile/guile-core/doc ChangeLog scheme-data.texi... |
Date: |
Sat, 05 May 2001 06:40:18 -0700 |
CVSROOT: /cvs
Module name: guile
Changes by: Neil Jerram <address@hidden> 01/05/05 06:40:18
Modified files:
guile-core/doc : ChangeLog scheme-data.texi
scheme-procedures.texi
Log message:
* New material on macros.
CVSWeb URLs:
http://savannah.gnu.org/cgi-bin/viewcvs/guile/guile-core/doc/ChangeLog.diff?cvsroot=OldCVS&tr1=1.82&tr2=1.83&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/guile/guile-core/doc/scheme-data.texi.diff?cvsroot=OldCVS&tr1=1.16&tr2=1.17&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/guile/guile-core/doc/scheme-procedures.texi.diff?cvsroot=OldCVS&tr1=1.9&tr2=1.10&r1=text&r2=text
Patches:
Index: guile/guile-core/doc/ChangeLog
diff -u guile/guile-core/doc/ChangeLog:1.82 guile/guile-core/doc/ChangeLog:1.83
--- guile/guile-core/doc/ChangeLog:1.82 Fri May 4 14:53:59 2001
+++ guile/guile-core/doc/ChangeLog Sat May 5 06:40:18 2001
@@ -1,3 +1,11 @@
+2001-05-05 Neil Jerram <address@hidden>
+
+ * scheme-procedures.texi (Macros, Syntax Rules, Internal Macros):
+ New material.
+ (Syntax Case): New node, but currently empty.
+
+ * scheme-data.texi (Booleans, Symbols): Supply cross-references.
+
2001-05-04 Neil Jerram <address@hidden>
* new-docstrings.texi, posix.texi, scheme-control.texi,
Index: guile/guile-core/doc/scheme-data.texi
diff -u guile/guile-core/doc/scheme-data.texi:1.16
guile/guile-core/doc/scheme-data.texi:1.17
--- guile/guile-core/doc/scheme-data.texi:1.16 Fri May 4 14:53:59 2001
+++ guile/guile-core/doc/scheme-data.texi Sat May 5 06:40:18 2001
@@ -69,7 +69,8 @@
Boolean values are returned by predicate procedures, such as the general
equality predicates @code{eq?}, @code{eqv?} and @code{equal?}
(@pxref{Equality}) and numerical and string comparison operators like
address@hidden (REFFIXME) and @code{<=} (REFFIXME).
address@hidden (@pxref{String Comparison}) and @code{<=}
+(@pxref{Comparison}).
@lisp
(<= 3 8)
@@ -89,8 +90,8 @@
#t
@end lisp
-In test condition contexts like @code{if} (REFFIXME) and @code{cond}
-(REFFIXME), where a group of subexpressions will be evaluated only if a
+In test condition contexts like @code{if} and @code{cond} (@pxref{if
+cond case}), where a group of subexpressions will be evaluated only if a
@var{condition} expression evaluates to ``true'', ``true'' means any
value at all except @code{#f}.
@@ -2312,9 +2313,9 @@
information for the human reader than, say, numbers.
It is very common in Scheme programs to use symbols as keys in
-association lists (REFFIXME) or hash tables (REFFIXME), because this
-usage improves the readability a lot, and does not cause any performance
-loss.
+association lists (@pxref{Association Lists}) or hash tables
+(@pxref{Hash Tables}), because this usage improves the readability a
+lot, and does not cause any performance loss.
The read syntax for symbols is a sequence of letters, digits, and
@emph{extended alphabetic characters} that begins with a character that
@@ -2329,10 +2330,10 @@
@end example
In addition to the read syntax defined above (which is taken from R5RS
-(REFFIXME)), Guile provides a method for writing symbols with unusual
-characters, such as space characters. If you (for whatever reason) need
-to write a symbol containing characters not mentioned above, you write
-symbols as follows:
+(@pxref{Formal syntax,,,r5rs,The Revised^5 Report on Scheme})), Guile
+provides a method for writing symbols with unusual characters, such as
+space characters. If you (for whatever reason) need to write a symbol
+containing characters not mentioned above, you write symbols as follows:
@itemize @bullet
@item
Index: guile/guile-core/doc/scheme-procedures.texi
diff -u guile/guile-core/doc/scheme-procedures.texi:1.9
guile/guile-core/doc/scheme-procedures.texi:1.10
--- guile/guile-core/doc/scheme-procedures.texi:1.9 Fri May 4 14:54:00 2001
+++ guile/guile-core/doc/scheme-procedures.texi Sat May 5 06:40:18 2001
@@ -7,7 +7,10 @@
* Optional Arguments:: Handling keyword, optional and rest arguments.
* Procedure Properties:: Procedure properties and metainformation.
* Procedures with Setters:: Procedures with setters.
-* Macros:: Macros.
+* Macros:: Lisp style macro definitions.
+* Syntax Rules:: Support for R5RS @code{syntax-rules}.
+* Syntax Case:: Support for the @code{syntax-case} system.
+* Internal Macros:: Guile's internal representation.
@end menu
@@ -500,54 +503,249 @@
@node Macros
address@hidden Macros
address@hidden Lisp Style Macro Definitions
-[FIXME: This needs some more text on the difference between procedures,
-macros and memoizing macros. Also, any definitions listed here should
-be double-checked by someone who knows what's going on. Ask Mikael, Jim
-or Aubrey for help. -twp]
address@hidden macros
address@hidden transformation
+Macros are objects which cause the expression that they appear in to be
+transformed in some way @emph{before} being evaluated. In expressions
+that are intended for macro transformation, the identifier that names
+the relevant macro must appear as the first element, like this:
address@hidden primitive procedure->syntax code
-Return a @dfn{macro} which, when a symbol defined to this value
-appears as the first symbol in an expression, returns the
-result of applying @var{code} to the expression and the
-environment.
address@hidden deffn
address@hidden
+(@var{macro-name} @var{macro-args} @dots{})
address@hidden lisp
address@hidden primitive procedure->macro code
-Return a @dfn{macro} which, when a symbol defined to this value
-appears as the first symbol in an expression, evaluates the
-result of applying @var{code} to the expression and the
-environment. The value returned from @var{code} which has been
-passed to @code{procedure->memoizing-macro} replaces the form
-passed to @var{code}. For example:
+In Lisp-like languages, the traditional way to define macros is very
+similar to procedure definitions. The key differences are that the
+macro definition body should return a list that describes the
+transformed expression, and that the definition is marked as a macro
+definition (rather than a procedure definition) by the use of a
+different definition keyword: in Lisp, @code{defmacro} rather than
address@hidden, and in Scheme, @code{define-macro} rather than
address@hidden
address@hidden defmacro
address@hidden define-macro
+Guile supports this style of macro definition using both @code{defmacro}
+and @code{define-macro}. The only difference between them is how the
+macro name and arguments are grouped together in the definition:
+
@lisp
-(define trace
- (procedure->macro
- (lambda (x env) `(set! ,(cadr x) (tracef ,(cadr x) ',(cadr x))))))
+(defmacro @var{name} (@var{args} @dots{}) @var{body} @dots{})
address@hidden lisp
+
address@hidden
+is the same as
+
address@hidden
+(define-macro (@var{name} @var{args} @dots{}) @var{body} @dots{})
address@hidden lisp
+
address@hidden
+The difference is analogous to the corresponding difference between
+Lisp's @code{defun} and Scheme's @code{define}.
+
address@hidden, from the @file{boot-9.scm} file in the Guile
+distribution, is a good example of macro definition using
address@hidden:
+
address@hidden
+(defmacro false-if-exception (expr)
+ `(catch #t
+ (lambda () ,expr)
+ (lambda args #f)))
address@hidden lisp
+
address@hidden
+The effect of this definition is that expressions beginning with the
+identifier @code{false-if-exception} are automatically transformed into
+a @code{catch} expression following the macro definition specification.
+For example:
+
address@hidden
+(false-if-exception (open-input-file "may-not-exist"))
address@hidden
+(catch #t
+ (lambda () (open-input-file "may-not-exist"))
+ (lambda args #f))
address@hidden lisp
+
+
address@hidden Syntax Rules
address@hidden The R5RS @code{syntax-rules} System
+
+R5RS defines an alternative system for macro and syntax transformations
+using the keywords @code{define-syntax}, @code{let-syntax},
address@hidden and @code{syntax-rules}.
+
+The main difference between the R5RS system and the traditional macros
+of the previous section is how the transformation is specified. In
+R5RS, rather than permitting a macro definition to return an arbitrary
+expression, the transformation is specified in a pattern language that
+
address@hidden @bullet
address@hidden
+does not require complicated quoting and extraction of components of the
+source expression using @code{caddr} etc.
+
address@hidden
+is designed such that the bindings associated with identifiers in the
+transformed expression are well defined, and such that it is impossible
+for the transformed expression to construct new identifiers.
address@hidden itemize
+
address@hidden
+The last point is commonly referred to as being @dfn{hygienic}: the R5RS
address@hidden system provides @dfn{hygienic macros}.
+
+For example, the R5RS pattern language for the @code{false-if-exception}
+example of the previous section looks like this:
+
address@hidden
+(syntax-rules ()
+ ((_ expr)
+ (catch #t
+ (lambda () expr)
+ (lambda args #f))))
address@hidden lisp
+
+In Guile, the @code{syntax-rules} system is provided by the @code{(ice-9
+syncase)} module. To make these facilities available in your code,
+include the expression @code{(use-modules (ice-9 syncase))} or
address@hidden(use-syntax (ice-9 syncase))} (@pxref{Loading Guile Modules})
+before the first usage of @code{define-syntax} etc. If you are writing
+a Scheme module, you can alternatively use one of the keywords
address@hidden:use-module} and @code{#:use-syntax} in your @code{define-module}
+declaration (@pxref{Creating Guile Modules}).
+
address@hidden
+* Pattern Language:: The @code{syntax-rules} pattern language.
+* Define-Syntax:: Top level syntax definitions.
+* Let-Syntax:: Local syntax definitions.
address@hidden menu
+
+
address@hidden Pattern Language
address@hidden The @code{syntax-rules} Pattern Language
+
+
address@hidden Define-Syntax
address@hidden Top Level Syntax Definitions
+
+define-syntax: The gist is
+
+ (define-syntax <keyword> <transformer-spec>)
+
+makes the <keyword> into a macro so that
+
+ (<keyword> ...)
+
+expands at _compile_ or _read_ time (i.e. before any
+evaluation begins) into some expression that is
+given by the <transformer-spec>.
+
+
address@hidden Let-Syntax
address@hidden Local Syntax Definitions
+
+
address@hidden Syntax Case
address@hidden Support for the @code{syntax-case} System
+
+
+
address@hidden Internal Macros
address@hidden Internal Representation of Macros and Syntax
-(trace @i{foo}) @equiv{} (set! @i{foo} (tracef @i{foo} '@i{foo})).
+Internally, Guile uses three different flavours of macros. The three
+flavours are called @dfn{acro} (or @dfn{syntax}), @dfn{macro} and
address@hidden
+
+Given the expression
+
address@hidden
+(foo @dots{})
@end lisp
+
address@hidden
+with @code{foo} being some flavour of macro, one of the following things
+will happen when the expression is evaluated.
+
address@hidden
address@hidden
+When @code{foo} has been defined to be an @dfn{acro}, the procedure used
+in the acro definition of @code{foo} is passed the whole expression and
+the current lexical environment, and whatever that procedure returns is
+the value of evaluating the expression. You can think of this a
+procedure that receives its argument as an unevaluated expression.
+
address@hidden
+When @code{foo} has been defined to be a @dfn{macro}, the procedure used
+in the macro definition of @code{foo} is passed the whole expression and
+the current lexical environment, and whatever that procedure returns is
+evaluated again. That is, the procedure should return a valid Scheme
+expression.
+
address@hidden
+When @code{foo} has been defined to be a @dfn{mmacro}, the procedure
+used in the mmacro definition of `foo' is passed the whole expression
+and the current lexical environment, and whatever that procedure returns
+replaces the original expression. Evaluation then starts over from the
+new expression that has just been returned.
address@hidden itemize
+
+The key difference between a @dfn{macro} and a @dfn{mmacro} is that the
+expression returned by a @dfn{mmacro} procedure is remembered (or
address@hidden) so that the expansion does not need to be done again
+next time the containing code is evaluated.
+
+The primitives @code{procedure->syntax}, @code{procedure->macro} and
address@hidden>memoizing-macro} are used to construct acros, macros
+and mmacros respectively. However, if you do not have a very special
+reason to use one of these primitives, you should avoid them: they are
+very specific to Guile's current implementation and therefore likely to
+change. Use @code{defmacro}, @code{define-macro} (@pxref{Macros}) or
address@hidden (@pxref{Syntax Rules}) instead. (In low level
+terms, @code{defmacro}, @code{define-macro} and @code{define-syntax} are
+all implemented as mmacros.)
+
address@hidden primitive procedure->syntax code
+Return a macro which, when a symbol defined to this value appears as the
+first symbol in an expression, returns the result of applying @var{code}
+to the expression and the environment.
@end deffn
address@hidden primitive procedure->memoizing-macro code
-Return a @dfn{macro} which, when a symbol defined to this value
-appears as the first symbol in an expression, evaluates the
-result of applying @var{proc} to the expression and the
-environment. The value returned from @var{proc} which has been
-passed to @code{procedure->memoizing-macro} replaces the form
-passed to @var{proc}. For example:
address@hidden primitive procedure->macro code
+Return a macro which, when a symbol defined to this value appears as the
+first symbol in an expression, evaluates the result of applying
address@hidden to the expression and the environment. For example:
@lisp
(define trace
(procedure->macro
- (lambda (x env) `(set! ,(cadr x) (tracef ,(cadr x) ',(cadr x))))))
+ (lambda (x env)
+ `(set! ,(cadr x) (tracef ,(cadr x) ',(cadr x))))))
-(trace @i{foo}) @equiv{} (set! @i{foo} (tracef @i{foo} '@i{foo})).
+(trace @i{foo})
address@hidden
+(set! @i{foo} (tracef @i{foo} '@i{foo})).
@end lisp
@end deffn
address@hidden primitive procedure->memoizing-macro code
+Return a macro which, when a symbol defined to this value appears as the
+first symbol in an expression, evaluates the result of applying
address@hidden to the expression and the environment.
address@hidden>memoizing-macro} is the same as
address@hidden>macro}, except that the expression returned by
address@hidden replaces the original macro expression in the memoized form
+of the containing code.
address@hidden deffn
+
+In the following primitives, @dfn{acro} flavour macros are referred to
+as @dfn{syntax transformers}.
+
@deffn primitive macro? obj
Return @code{#t} if @var{obj} is a regular macro, a memoizing macro or a
syntax transformer.
@@ -556,7 +754,7 @@
@deffn primitive macro-type m
Return one of the symbols @code{syntax}, @code{macro} or
@code{macro!}, depending on whether @var{m} is a syntax
-tranformer, a regular macro, or a memoizing macro,
+transformer, a regular macro, or a memoizing macro,
respectively. If @var{m} is not a macro, @code{#f} is
returned.
@end deffn