summaryrefslogtreecommitdiff
path: root/doc/ref/api-macros.texi
diff options
context:
space:
mode:
authorAndy Wingo <wingo@pobox.com>2012-01-10 00:41:42 +0100
committerAndy Wingo <wingo@pobox.com>2012-01-10 00:41:42 +0100
commit91ee7515da0bad91330ce5c87b250d6cf12a2789 (patch)
treece023c92c0d9bf895c1265b107b270c35ba59b94 /doc/ref/api-macros.texi
parent0bdd43515eb3c62839512181cf33e5aea383e661 (diff)
parent0e947e1d14597651c5762a4209225c472bdaef45 (diff)
downloadguile-91ee7515da0bad91330ce5c87b250d6cf12a2789.tar.gz
Merge remote-tracking branch 'origin/stable-2.0'
Conflicts: libguile/__scm.h libguile/array-map.c libguile/procprop.c libguile/tags.h module/ice-9/deprecated.scm module/ice-9/psyntax-pp.scm module/ice-9/psyntax.scm test-suite/standalone/test-num2integral.c test-suite/tests/regexp.test
Diffstat (limited to 'doc/ref/api-macros.texi')
-rw-r--r--doc/ref/api-macros.texi78
1 files changed, 77 insertions, 1 deletions
diff --git a/doc/ref/api-macros.texi b/doc/ref/api-macros.texi
index 92816ad82..e60864ba3 100644
--- a/doc/ref/api-macros.texi
+++ b/doc/ref/api-macros.texi
@@ -1,6 +1,6 @@
@c -*-texinfo-*-
@c This is part of the GNU Guile Reference Manual.
-@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2009, 2010, 2011
+@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2009, 2010, 2011, 2012
@c Free Software Foundation, Inc.
@c See the file guile.texi for copying conditions.
@@ -40,6 +40,7 @@ languages}, or EDSLs.}.
* Syntax Case:: Procedural, hygienic macros.
* Defmacros:: Lisp-style macros.
* Identifier Macros:: Identifier macros.
+* Syntax Parameters:: Syntax Parameters
* Eval When:: Affecting the expand-time environment.
* Internal Macros:: Macros as first-class values.
@end menu
@@ -861,6 +862,81 @@ wrapping in @code{#'} syntax forms.
@end deffn
+@node Syntax Parameters
+@subsection Syntax Parameters
+
+Syntax parameters@footnote{Described in the paper @cite{Keeping it Clean
+with Syntax Parameters} by Barzilay, Culpepper and Flatt.} are a
+mechanism for rebinding a macro definition within the dynamic extent of
+a macro expansion. This provides a convenient solution to one of the
+most common types of unhygienic macro: those that introduce a unhygienic
+binding each time the macro is used. Examples include a @code{lambda}
+form with a @code{return} keyword, or class macros that introduce a
+special @code{self} binding.
+
+With syntax parameters, instead of introducing the binding
+unhygienically each time, we instead create one binding for the keyword,
+which we can then adjust later when we want the keyword to have a
+different meaning. As no new bindings are introduced, hygiene is
+preserved. This is similar to the dynamic binding mechanisms we have at
+run-time (@pxref{SRFI-39, parameters}), except that the dynamic binding
+only occurs during macro expansion. The code after macro expansion
+remains lexically scoped.
+
+@deffn {Syntax} define-syntax-parameter keyword transformer
+Binds @var{keyword} to the value obtained by evaluating
+@var{transformer}. The @var{transformer} provides the default expansion
+for the syntax parameter, and in the absence of
+@code{syntax-parameterize}, is functionally equivalent to
+@code{define-syntax}. Usually, you will just want to have the
+@var{transformer} throw a syntax error indicating that the @var{keyword}
+is supposed to be used in conjunction with another macro, for example:
+@example
+(define-syntax-parameter return
+ (lambda (stx)
+ (syntax-violation 'return "return used outside of a lambda^" stx)))
+@end example
+@end deffn
+
+@deffn {Syntax} syntax-parameterize ((keyword transformer) @dots{}) exp @dots{}
+Adjusts @var{keyword} @dots{} to use the values obtained by evaluating
+their @var{transformer} @dots{}, in the expansion of the @var{exp}
+@dots{} forms. Each @var{keyword} must be bound to a syntax-parameter.
+@code{syntax-parameterize} differs from @code{let-syntax}, in that the
+binding is not shadowed, but adjusted, and so uses of the keyword in the
+expansion of @var{exp} @dots{} use the new transformers. This is
+somewhat similar to how @code{parameterize} adjusts the values of
+regular parameters, rather than creating new bindings.
+
+@example
+(define-syntax lambda^
+ (syntax-rules ()
+ [(lambda^ argument-list body body* ...)
+ (lambda argument-list
+ (call-with-current-continuation
+ (lambda (escape)
+ ;; In the body we adjust the 'return' keyword so that calls
+ ;; to 'return' are replaced with calls to the escape
+ ;; continuation.
+ (syntax-parameterize ([return (syntax-rules ()
+ [(return vals (... ...))
+ (escape vals (... ...))])])
+ body body* ...))))]))
+
+;; Now we can write functions that return early. Here, 'product' will
+;; return immediately if it sees any 0 element.
+(define product
+ (lambda^ (list)
+ (fold (lambda (n o)
+ (if (zero? n)
+ (return 0)
+ (* n o)))
+ 1
+ list)))
+@end example
+@end deffn
+
+
@node Eval When
@subsection Eval-when