diff options
author | Marius Vollmer <mvo@zagadka.de> | 2004-08-02 12:29:00 +0000 |
---|---|---|
committer | Marius Vollmer <mvo@zagadka.de> | 2004-08-02 12:29:00 +0000 |
commit | 07d83abe7b8b617e4bb70a08efc0c0f6999fa0cc (patch) | |
tree | 34c8a7b9d98000169379038be8551ed44c0bdb83 /doc/ref/api-procedures.texi | |
parent | 237be238424f1b6d130799ad931ba6fa8504a97c (diff) | |
download | guile-07d83abe7b8b617e4bb70a08efc0c0f6999fa0cc.tar.gz |
* scheme-binding.texi: Renamed to api-binding.texi.
* scheme-compound.texi: Renamed to api-compound.texi.
* scheme-control.texi: Renamed to api-control.texi.
* scheme-data.texi: Renamed to api-data.texi.
* scheme-debug.texi: Renamed to api-debug.texi.
* deprecated.texi: Renamed to api-deprecated.texi.
* scheme-evaluation.texi: Renamed to api-evaluation.texi.
* ref-init.texi: Renamed to api-init.texi.
* scheme-io.texi: Renamed to api-io.texi.
* scheme-memory.texi: Renamed to api-memory.texi.
* scheme-modules.texi: Renamed to api-modules.texi.
* scheme-options.texi: Renamed to api-options.texi.
* scm.texi: Renamed to api-overview.texi.
* scheme-procedures.texi: Renamed to api-procedures.texi.
* scheme-scheduling.texi: Renamed to api-scheduling.texi.
* scheme-scm.texi: Renamed to api-scm.texi.
* scheme-smobs.texi: Renamed to api-smobs.texi.
* scheme-snarf.texi: Renamed to api-snarf.texi.
* scheme-translation.texi: Renamed to api-translation.texi.
* scheme-utility.texi: Renamed to api-utility.texi.
* debugging.texi: Renamed to scheme-debugging.texi.
* scripts.texi: Renamed to scheme-scripts.texi.
* program.texi: Renamed to libguile-program.texi.
Diffstat (limited to 'doc/ref/api-procedures.texi')
-rw-r--r-- | doc/ref/api-procedures.texi | 859 |
1 files changed, 859 insertions, 0 deletions
diff --git a/doc/ref/api-procedures.texi b/doc/ref/api-procedures.texi new file mode 100644 index 000000000..08ae7c2c5 --- /dev/null +++ b/doc/ref/api-procedures.texi @@ -0,0 +1,859 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@page +@node Procedures and Macros +@section Procedures and Macros + +@menu +* Lambda:: Basic procedure creation using lambda. +* Primitive Procedures:: Procedures defined in C. +* Optional Arguments:: Handling keyword, optional and rest arguments. +* Procedure Properties:: Procedure properties and meta-information. +* Procedures with Setters:: Procedures with setters. +* 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 + + +@node Lambda +@subsection Lambda: Basic Procedure Creation +@cindex lambda + +@c FIXME::martin: Review me! + +A @code{lambda} expression evaluates to a procedure. The environment +which is in effect when a @code{lambda} expression is evaluated is +enclosed in the newly created procedure, this is referred to as a +@dfn{closure} (@pxref{About Closure}). + +When a procedure created by @code{lambda} is called with some actual +arguments, the environment enclosed in the procedure is extended by +binding the variables named in the formal argument list to new locations +and storing the actual arguments into these locations. Then the body of +the @code{lambda} expression is evaluation sequentially. The result of +the last expression in the procedure body is then the result of the +procedure invocation. + +The following examples will show how procedures can be created using +@code{lambda}, and what you can do with these procedures. + +@lisp +(lambda (x) (+ x x)) @result{} @r{a procedure} +((lambda (x) (+ x x)) 4) @result{} 8 +@end lisp + +The fact that the environment in effect when creating a procedure is +enclosed in the procedure is shown with this example: + +@lisp +(define add4 + (let ((x 4)) + (lambda (y) (+ x y)))) +(add4 6) @result{} 10 +@end lisp + + +@deffn syntax lambda formals body +@var{formals} should be a formal argument list as described in the +following table. + +@table @code +@item (@var{variable1} @dots{}) +The procedure takes a fixed number of arguments; when the procedure is +called, the arguments will be stored into the newly created location for +the formal variables. +@item @var{variable} +The procedure takes any number of arguments; when the procedure is +called, the sequence of actual arguments will converted into a list and +stored into the newly created location for the formal variable. +@item (@var{variable1} @dots{} @var{variablen} . @var{variablen+1}) +If a space-delimited period precedes the last variable, then the +procedure takes @var{n} or more variables where @var{n} is the number +of formal arguments before the period. There must be at least one +argument before the period. The first @var{n} actual arguments will be +stored into the newly allocated locations for the first @var{n} formal +arguments and the sequence of the remaining actual arguments is +converted into a list and the stored into the location for the last +formal argument. If there are exactly @var{n} actual arguments, the +empty list is stored into the location of the last formal argument. +@end table + +The list in @var{variable} or @var{variablen+1} is always newly +created and the procedure can modify it if desired. This is the case +even when the procedure is invoked via @code{apply}, the required part +of the list argument there will be copied (@pxref{Fly Evaluation,, +Procedures for On the Fly Evaluation}). + +@var{body} is a sequence of Scheme expressions which are evaluated in +order when the procedure is invoked. +@end deffn + +@node Primitive Procedures +@subsection Primitive Procedures +@cindex primitives +@cindex primitive procedures + +Procedures written in C can be registered for use from Scheme, +provided they take only arguments of type @code{SCM} and return +@code{SCM} values. @code{scm_c_define_gsubr} is likely to be the most +useful mechanism, combining the process of registration +(@code{scm_c_make_gsubr}) and definition (@code{scm_define}). + +@deftypefun SCM scm_c_make_gsubr (const char *name, int req, int opt, int rst, fcn) +Register a C procedure @var{FCN} as a ``subr'' --- a primitive +subroutine that can be called from Scheme. It will be associated with +the given @var{name} but no environment binding will be created. The +arguments @var{req}, @var{opt} and @var{rst} specify the number of +required, optional and ``rest'' arguments respectively. The total +number of these arguments should match the actual number of arguments +to @var{fcn}. The number of rest arguments should be 0 or 1. +@code{scm_c_make_gsubr} returns a value of type @code{SCM} which is a +``handle'' for the procedure. +@end deftypefun + +@deftypefun SCM scm_c_define_gsubr (const char *name, int req, int opt, int rst, fcn) +Register a C procedure @var{FCN}, as for @code{scm_c_make_gsubr} +above, and additionally create a top-level Scheme binding for the +procedure in the ``current environment'' using @code{scm_define}. +@code{scm_c_define_gsubr} returns a handle for the procedure in the +same way as @code{scm_c_make_gsubr}, which is usually not further +required. +@end deftypefun + +@code{scm_c_make_gsubr} and @code{scm_c_define_gsubr} automatically +use @code{scm_c_make_subr} and also @code{scm_makcclo} if necessary. +It is advisable to use the gsubr variants since they provide a +slightly higher-level abstraction of the Guile implementation. + +@node Optional Arguments +@subsection Optional Arguments + +@c FIXME::martin: Review me! + +Scheme procedures, as defined in R5RS, can either handle a fixed number +of actual arguments, or a fixed number of actual arguments followed by +arbitrarily many additional arguments. Writing procedures of variable +arity can be useful, but unfortunately, the syntactic means for handling +argument lists of varying length is a bit inconvenient. It is possible +to give names to the fixed number of argument, but the remaining +(optional) arguments can be only referenced as a list of values +(@pxref{Lambda}). + +Guile comes with the module @code{(ice-9 optargs)}, which makes using +optional arguments much more convenient. In addition, this module +provides syntax for handling keywords in argument lists +(@pxref{Keywords}). + +Before using any of the procedures or macros defined in this section, +you have to load the module @code{(ice-9 optargs)} with the statement: + +@cindex @code{optargs} +@lisp +(use-modules (ice-9 optargs)) +@end lisp + +@menu +* let-optional Reference:: Locally binding optional arguments. +* let-keywords Reference:: Locally binding keywords arguments. +* lambda* Reference:: Creating advanced argument handling procedures. +* define* Reference:: Defining procedures and macros. +@end menu + + +@node let-optional Reference +@subsubsection let-optional Reference + +@c FIXME::martin: Review me! + +The syntax @code{let-optional} and @code{let-optional*} are for +destructuring rest argument lists and giving names to the various list +elements. @code{let-optional} binds all variables simultaneously, while +@code{let-optional*} binds them sequentially, consistent with @code{let} +and @code{let*} (@pxref{Local Bindings}). + +@deffn {library syntax} let-optional rest-arg (binding @dots{}) expr @dots{} +@deffnx {library syntax} let-optional* rest-arg (binding @dots{}) expr @dots{} +These two macros give you an optional argument interface that is very +@dfn{Schemey} and introduces no fancy syntax. They are compatible with +the scsh macros of the same name, but are slightly extended. Each of +@var{binding} may be of one of the forms @var{var} or @code{(@var{var} +@var{default-value})}. @var{rest-arg} should be the rest-argument of the +procedures these are used from. The items in @var{rest-arg} are +sequentially bound to the variable names are given. When @var{rest-arg} +runs out, the remaining vars are bound either to the default values or +@code{#f} if no default value was specified. @var{rest-arg} remains +bound to whatever may have been left of @var{rest-arg}. + +After binding the variables, the expressions @var{expr} @dots{} are +evaluated in order. +@end deffn + + +@node let-keywords Reference +@subsubsection let-keywords Reference + +@c FIXME::martin: Review me! + +@code{let-keywords} and @code{let-keywords*} are used for extracting +values from argument lists which use keywords instead of argument +position for binding local variables to argument values. + +@code{let-keywords} binds all variables simultaneously, while +@code{let-keywords*} binds them sequentially, consistent with @code{let} +and @code{let*} (@pxref{Local Bindings}). + +@deffn {library syntax} let-keywords rest-arg allow-other-keys? (binding @dots{}) expr @dots{} +@deffnx {library syntax} let-keywords rest-arg allow-other-keys? (binding @dots{}) expr @dots{} +These macros pick out keyword arguments from @var{rest-arg}, but do not +modify it. This is consistent at least with Common Lisp, which +duplicates keyword arguments in the rest argument. More explanation of what +keyword arguments in a lambda list look like can be found below in +the documentation for @code{lambda*} + (@pxref{lambda* Reference}). @var{binding}s can have the same form as +for @code{let-optional}. If @var{allow-other-keys?} is false, an error +will be thrown if anything that looks like a keyword argument but does +not match a known keyword parameter will result in an error. + +After binding the variables, the expressions @var{expr} @dots{} are +evaluated in order. +@end deffn + + +@node lambda* Reference +@subsubsection lambda* Reference + +@c FIXME::martin: Review me! + +When using optional and keyword argument lists, using @code{lambda} for +creating procedures and using @code{let-optional} or @code{let-keywords} +is a bit lengthy. Therefore, @code{lambda*} is provided, which combines +the features of those macros into a single convenient syntax. + +For quick reference, here is the syntax of the formal argument list for +@code{lambda*} (brackets are used to indicate grouping only): + +@example +ext-param-list ::= [identifier]* [#:optional [ext-var-decl]+]? + [#:key [ext-var-decl]+ [#:allow-other-keys]?]? + [[#:rest identifier]|[. identifier]]? + +ext-var-decl ::= identifier | ( identifier expression ) +@end example + +The characters `*', `+' and `?' are not to be taken literally; they mean +respectively, zero or more occurrences, one or more occurrences, and one +or zero occurrences. + +@deffn {library syntax} lambda* formals body +@code{lambda*} creates a procedure that takes optional arguments. These +are specified by putting them inside brackets at the end of the +parameter list, but before any dotted rest argument. For example, + +@lisp +(lambda* (a b #:optional c d . e) '()) +@end lisp + +creates a procedure with fixed arguments @var{a} and @var{b}, optional +arguments @var{c} and @var{d}, and rest argument @var{e}. If the +optional arguments are omitted in a call, the variables for them are +bound to @code{#f}. + +@code{lambda*} can also take keyword arguments. For example, a procedure +defined like this: + +@lisp +(lambda* (#:key xyzzy larch) '()) +@end lisp + +can be called with any of the argument lists @code{(#:xyzzy 11)} +@code{(#:larch 13)} @code{(#:larch 42 #:xyzzy 19)} @code{()}. Whichever +arguments are given as keywords are bound to values. + +Optional and keyword arguments can also be given default values +which they take on when they are not present in a call, by giving a +two-item list in place of an optional argument, for example in: + +@lisp +(lambda* (foo #:optional (bar 42) #:key (baz 73)) + (list foo bar baz)) +@end lisp + +@var{foo} is a fixed argument, @var{bar} is an optional argument with +default value 42, and baz is a keyword argument with default value 73. +Default value expressions are not evaluated unless they are needed and +until the procedure is called. + +@code{lambda*} also supports two more special parameter list keywords. + +@code{lambda*}-defined procedures now throw an error by default if a +keyword other than one of those specified is found in the actual +passed arguments. However, specifying @code{#:allow-other-keys} +immediately after the keyword argument declarations restores the +previous behavior of ignoring unknown keywords. @code{lambda*} also now +guarantees that if the same keyword is passed more than once, the +last one passed is the one that takes effect. For example, + +@lisp +((lambda* (#:key (heads 0) (tails 0)) (display (list heads tails))) + #:heads 37 #:tails 42 #:heads 99) +@end lisp + +would result in (99 47) being displayed. + +@code{#:rest} is also now provided as a synonym for the dotted syntax +rest argument. The argument lists @code{(a . b)} and @code{(a #:rest b)} +are equivalent in all respects to @code{lambda*}. This is provided for +more similarity to DSSSL, MIT-Scheme and Kawa among others, as well as +for refugees from other Lisp dialects. +@end deffn + + +@node define* Reference +@subsubsection define* Reference + +@c FIXME::martin: Review me! + +Just like @code{define} has a shorthand notation for defining procedures +(@pxref{Lambda Alternatives}), @code{define*} is provided as an +abbreviation of the combination of @code{define} and @code{lambda*}. + +@code{define*-public} is the @code{lambda*} version of +@code{define-public}; @code{defmacro*} and @code{defmacro*-public} exist +for defining macros with the improved argument list handling +possibilities. The @code{-public} versions not only define the +procedures/macros, but also export them from the current module. + +@deffn {library syntax} define* formals body +@deffnx {library syntax} define*-public formals body +@code{define*} and @code{define*-public} support optional arguments with +a similar syntax to @code{lambda*}. They also support arbitrary-depth +currying, just like Guile's define. Some examples: + +@lisp +(define* (x y #:optional a (z 3) #:key w . u) + (display (list y z u))) +@end lisp +defines a procedure @code{x} with a fixed argument @var{y}, an optional +argument @var{a}, another optional argument @var{z} with default value 3, +a keyword argument @var{w}, and a rest argument @var{u}. + +@lisp +(define-public* ((foo #:optional bar) #:optional baz) '()) +@end lisp + +This illustrates currying. A procedure @code{foo} is defined, which, +when called with an optional argument @var{bar}, returns a procedure +that takes an optional argument @var{baz}. + +Of course, @code{define*[-public]} also supports @code{#:rest} and +@code{#:allow-other-keys} in the same way as @code{lambda*}. +@end deffn + +@deffn {library syntax} defmacro* name formals body +@deffnx {library syntax} defmacro*-public name formals body +These are just like @code{defmacro} and @code{defmacro-public} except that they +take @code{lambda*}-style extended parameter lists, where @code{#:optional}, +@code{#:key}, @code{#:allow-other-keys} and @code{#:rest} are allowed with the usual +semantics. Here is an example of a macro with an optional argument: + +@lisp +(defmacro* transmorgify (a #:optional b) + (a 1)) +@end lisp +@end deffn + + +@node Procedure Properties +@subsection Procedure Properties and Meta-information + +@c FIXME::martin: Review me! + +Procedures always have attached the environment in which they were +created and information about how to apply them to actual arguments. In +addition to that, properties and meta-information can be stored with +procedures. The procedures in this section can be used to test whether +a given procedure satisfies a condition; and to access and set a +procedure's property. + +The first group of procedures are predicates to test whether a Scheme +object is a procedure, or a special procedure, respectively. +@code{procedure?} is the most general predicates, it returns @code{#t} +for any kind of procedure. @code{closure?} does not return @code{#t} +for primitive procedures, and @code{thunk?} only returns @code{#t} for +procedures which do not accept any arguments. + +@rnindex procedure? +@deffn {Scheme Procedure} procedure? obj +@deffnx {C Function} scm_procedure_p (obj) +Return @code{#t} if @var{obj} is a procedure. +@end deffn + +@deffn {Scheme Procedure} closure? obj +@deffnx {C Function} scm_closure_p (obj) +Return @code{#t} if @var{obj} is a closure. +@end deffn + +@deffn {Scheme Procedure} thunk? obj +@deffnx {C Function} scm_thunk_p (obj) +Return @code{#t} if @var{obj} is a thunk. +@end deffn + +@c FIXME::martin: Is that true? +@cindex procedure properties +Procedure properties are general properties to be attached to +procedures. These can be the name of a procedure or other relevant +information, such as debug hints. + +@deffn {Scheme Procedure} procedure-name proc +@deffnx {C Function} scm_procedure_name (proc) +Return the name of the procedure @var{proc} +@end deffn + +@deffn {Scheme Procedure} procedure-source proc +@deffnx {C Function} scm_procedure_source (proc) +Return the source of the procedure @var{proc}. +@end deffn + +@deffn {Scheme Procedure} procedure-environment proc +@deffnx {C Function} scm_procedure_environment (proc) +Return the environment of the procedure @var{proc}. +@end deffn + +@deffn {Scheme Procedure} procedure-properties proc +@deffnx {C Function} scm_procedure_properties (proc) +Return @var{obj}'s property list. +@end deffn + +@deffn {Scheme Procedure} procedure-property obj key +@deffnx {C Function} scm_procedure_property (obj, key) +Return the property of @var{obj} with name @var{key}. +@end deffn + +@deffn {Scheme Procedure} set-procedure-properties! proc alist +@deffnx {C Function} scm_set_procedure_properties_x (proc, alist) +Set @var{obj}'s property list to @var{alist}. +@end deffn + +@deffn {Scheme Procedure} set-procedure-property! obj key value +@deffnx {C Function} scm_set_procedure_property_x (obj, key, value) +In @var{obj}'s property list, set the property named @var{key} to +@var{value}. +@end deffn + +@cindex procedure documentation +Documentation for a procedure can be accessed with the procedure +@code{procedure-documentation}. + +@deffn {Scheme Procedure} procedure-documentation proc +@deffnx {C Function} scm_procedure_documentation (proc) +Return the documentation string associated with @code{proc}. By +convention, if a procedure contains more than one expression and the +first expression is a string constant, that string is assumed to contain +documentation for that procedure. +@end deffn + +@cindex source properties +@c FIXME::martin: Is the following true? +Source properties are properties which are related to the source code of +a procedure, such as the line and column numbers, the file name etc. + +@deffn {Scheme Procedure} set-source-properties! obj plist +@deffnx {C Function} scm_set_source_properties_x (obj, plist) +Install the association list @var{plist} as the source property +list for @var{obj}. +@end deffn + +@deffn {Scheme Procedure} set-source-property! obj key datum +@deffnx {C Function} scm_set_source_property_x (obj, key, datum) +Set the source property of object @var{obj}, which is specified by +@var{key} to @var{datum}. Normally, the key will be a symbol. +@end deffn + +@deffn {Scheme Procedure} source-properties obj +@deffnx {C Function} scm_source_properties (obj) +Return the source property association list of @var{obj}. +@end deffn + + +@deffn {Scheme Procedure} source-property obj key +@deffnx {C Function} scm_source_property (obj, key) +Return the source property specified by @var{key} from +@var{obj}'s source property list. +@end deffn + + +@node Procedures with Setters +@subsection Procedures with Setters + +@c FIXME::martin: Review me! + +@c FIXME::martin: Document `operator struct'. + +@cindex procedure with setter +@cindex setter +A @dfn{procedure with setter} is a special kind of procedure which +normally behaves like any accessor procedure, that is a procedure which +accesses a data structure. The difference is that this kind of +procedure has a so-called @dfn{setter} attached, which is a procedure +for storing something into a data structure. + +Procedures with setters are treated specially when the procedure appears +in the special form @code{set!} (REFFIXME). How it works is best shown +by example. + +Suppose we have a procedure called @code{foo-ref}, which accepts two +arguments, a value of type @code{foo} and an integer. The procedure +returns the value stored at the given index in the @code{foo} object. +Let @code{f} be a variable containing such a @code{foo} data +structure.@footnote{Working definitions would be: +@lisp +(define foo-ref vector-ref) +(define foo-set! vector-set!) +(define f (make-vector 2 #f)) +@end lisp +} + +@lisp +(foo-ref f 0) @result{} bar +(foo-ref f 1) @result{} braz +@end lisp + +Also suppose that a corresponding setter procedure called +@code{foo-set!} does exist. + +@lisp +(foo-set! f 0 'bla) +(foo-ref f 0) @result{} bla +@end lisp + +Now we could create a new procedure called @code{foo}, which is a +procedure with setter, by calling @code{make-procedure-with-setter} with +the accessor and setter procedures @code{foo-ref} and @code{foo-set!}. +Let us call this new procedure @code{foo}. + +@lisp +(define foo (make-procedure-with-setter foo-ref foo-set!)) +@end lisp + +@code{foo} can from now an be used to either read from the data +structure stored in @code{f}, or to write into the structure. + +@lisp +(set! (foo f 0) 'dum) +(foo f 0) @result{} dum +@end lisp + +@deffn {Scheme Procedure} make-procedure-with-setter procedure setter +@deffnx {C Function} scm_make_procedure_with_setter (procedure, setter) +Create a new procedure which behaves like @var{procedure}, but +with the associated setter @var{setter}. +@end deffn + +@deffn {Scheme Procedure} procedure-with-setter? obj +@deffnx {C Function} scm_procedure_with_setter_p (obj) +Return @code{#t} if @var{obj} is a procedure with an +associated setter procedure. +@end deffn + +@deffn {Scheme Procedure} procedure proc +@deffnx {C Function} scm_procedure (proc) +Return the procedure of @var{proc}, which must be either a +procedure with setter, or an operator struct. +@end deffn + +@deffn {Scheme Procedure} setter proc +Return the setter of @var{proc}, which must be either a procedure with +setter or an operator struct. +@end deffn + + +@node Macros +@subsection Lisp Style Macro Definitions + +@cindex macros +@cindex 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: + +@lisp +(@var{macro-name} @var{macro-args} @dots{}) +@end lisp + +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 +@code{defun}, and in Scheme, @code{define-macro} rather than +@code{define}. + +@fnindex defmacro +@fnindex 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 +(defmacro @var{name} (@var{args} @dots{}) @var{body} @dots{}) +@end lisp + +@noindent +is the same as + +@lisp +(define-macro (@var{name} @var{args} @dots{}) @var{body} @dots{}) +@end lisp + +@noindent +The difference is analogous to the corresponding difference between +Lisp's @code{defun} and Scheme's @code{define}. + +@code{false-if-exception}, from the @file{boot-9.scm} file in the Guile +distribution, is a good example of macro definition using +@code{defmacro}: + +@lisp +(defmacro false-if-exception (expr) + `(catch #t + (lambda () ,expr) + (lambda args #f))) +@end lisp + +@noindent +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: + +@lisp +(false-if-exception (open-input-file "may-not-exist")) +@equiv{} +(catch #t + (lambda () (open-input-file "may-not-exist")) + (lambda args #f)) +@end lisp + + +@node Syntax Rules +@subsection The R5RS @code{syntax-rules} System +@cindex R5RS syntax-rules system + +R5RS defines an alternative system for macro and syntax transformations +using the keywords @code{define-syntax}, @code{let-syntax}, +@code{letrec-syntax} 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 + +@itemize @bullet +@item +does not require complicated quoting and extraction of components of the +source expression using @code{caddr} etc. + +@item +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. +@end itemize + +@noindent +The last point is commonly referred to as being @dfn{hygienic}: the R5RS +@code{syntax-case} 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: + +@lisp +(syntax-rules () + ((_ expr) + (catch #t + (lambda () expr) + (lambda args #f)))) +@end lisp + +@cindex @code{syncase} +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-syntax (ice-9 syncase))} (@pxref{Using +Guile Modules}) before the first usage of @code{define-syntax} etc. If +you are writing a Scheme module, you can alternatively include the form +@code{#:use-syntax (ice-9 syncase)} in your @code{define-module} +declaration (@pxref{Creating Guile Modules}). + +@menu +* Pattern Language:: The @code{syntax-rules} pattern language. +* Define-Syntax:: Top level syntax definitions. +* Let-Syntax:: Local syntax definitions. +@end menu + + +@node Pattern Language +@subsubsection The @code{syntax-rules} Pattern Language + + +@node Define-Syntax +@subsubsection 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>. + + +@node Let-Syntax +@subsubsection Local Syntax Definitions + + +@node Syntax Case +@subsection Support for the @code{syntax-case} System + + + +@node Internal Macros +@subsection Internal Representation of Macros and Syntax + +Internally, Guile uses three different flavors of macros. The three +flavors are called @dfn{acro} (or @dfn{syntax}), @dfn{macro} and +@dfn{mmacro}. + +Given the expression + +@lisp +(foo @dots{}) +@end lisp + +@noindent +with @code{foo} being some flavor of macro, one of the following things +will happen when the expression is evaluated. + +@itemize @bullet +@item +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. + +@item +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. + +@item +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. +@end 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 +@dfn{memoized}) 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 +@code{procedure->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 +@code{define-syntax} (@pxref{Syntax Rules}) instead. (In low level +terms, @code{defmacro}, @code{define-macro} and @code{define-syntax} are +all implemented as mmacros.) + +@deffn {Scheme Procedure} procedure->syntax code +@deffnx {C Function} scm_makacro (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 + +@deffn {Scheme Procedure} procedure->macro code +@deffnx {C Function} scm_makmacro (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 +@var{code} to the expression and the environment. For example: + +@lisp +(define trace + (procedure->macro + (lambda (x env) + `(set! ,(cadr x) (tracef ,(cadr x) ',(cadr x)))))) + +(trace @i{foo}) +@equiv{} +(set! @i{foo} (tracef @i{foo} '@i{foo})). +@end lisp +@end deffn + +@deffn {Scheme Procedure} procedure->memoizing-macro code +@deffnx {C Function} scm_makmmacro (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 +@var{code} to the expression and the environment. +@code{procedure->memoizing-macro} is the same as +@code{procedure->macro}, except that the expression returned by +@var{code} replaces the original macro expression in the memoized form +of the containing code. +@end deffn + +In the following primitives, @dfn{acro} flavor macros are referred to +as @dfn{syntax transformers}. + +@deffn {Scheme Procedure} macro? obj +@deffnx {C Function} scm_macro_p (obj) +Return @code{#t} if @var{obj} is a regular macro, a memoizing macro or a +syntax transformer. +@end deffn + +@deffn {Scheme Procedure} macro-type m +@deffnx {C Function} scm_macro_type (m) +Return one of the symbols @code{syntax}, @code{macro} or +@code{macro!}, depending on whether @var{m} is a syntax +transformer, a regular macro, or a memoizing macro, +respectively. If @var{m} is not a macro, @code{#f} is +returned. +@end deffn + +@deffn {Scheme Procedure} macro-name m +@deffnx {C Function} scm_macro_name (m) +Return the name of the macro @var{m}. +@end deffn + +@deffn {Scheme Procedure} macro-transformer m +@deffnx {C Function} scm_macro_transformer (m) +Return the transformer of the macro @var{m}. +@end deffn + +@deffn {Scheme Procedure} cons-source xorig x y +@deffnx {C Function} scm_cons_source (xorig, x, y) +Create and return a new pair whose car and cdr are @var{x} and @var{y}. +Any source properties associated with @var{xorig} are also associated +with the new pair. +@end deffn + + +@c Local Variables: +@c TeX-master: "guile.texi" +@c End: |