guile-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Guile-commits] GNU Guile branch, master, updated. release_1-9-9-3-g6ffd


From: Andy Wingo
Subject: [Guile-commits] GNU Guile branch, master, updated. release_1-9-9-3-g6ffd413
Date: Fri, 19 Mar 2010 12:52:46 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU Guile".

http://git.savannah.gnu.org/cgit/guile.git/commit/?id=6ffd4131ffa11d0a91cc555641f40457fd2ba7d0

The branch, master has been updated
       via  6ffd4131ffa11d0a91cc555641f40457fd2ba7d0 (commit)
       via  1fc8dcc7ac6a83ae6586e02491784954e3be94ef (commit)
       via  a6e60a9571711cf90ec9cf547125cb1495e58bca (commit)
      from  fbda9ef1b24d70edd3ebab0f9e8a29b8fdfba852 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 6ffd4131ffa11d0a91cc555641f40457fd2ba7d0
Author: Andy Wingo <address@hidden>
Date:   Fri Mar 19 13:16:57 2010 +0100

    finish macro docs
    
    * doc/ref/api-macros.texi: Finish macro docs.

commit 1fc8dcc7ac6a83ae6586e02491784954e3be94ef
Author: Andy Wingo <address@hidden>
Date:   Fri Mar 19 12:30:31 2010 +0100

    document syntax-case
    
    * doc/ref/api-macros.texi: Document syntax-case, and tweak defmacro
      docs.
    
    * doc/ref/api-debug.texi: Move cons-source here.

commit a6e60a9571711cf90ec9cf547125cb1495e58bca
Author: Andy Wingo <address@hidden>
Date:   Fri Mar 19 12:01:55 2010 +0100

    add GUILE-VERSION to CONFIG_STATUS_DEPENDENCIES
    
    * Makefile.am (CONFIG_STATUS_DEPENDENCIES): Add GUILE-VERSION, so that a
      change in GUILE-VERSION causes a reconfigure.

-----------------------------------------------------------------------

Summary of changes:
 Makefile.am             |    2 +
 doc/ref/api-debug.texi  |   11 +
 doc/ref/api-macros.texi |  506 ++++++++++++++++++++++++++++++++++++++++++-----
 3 files changed, 468 insertions(+), 51 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index bbd1352..3705762 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -48,6 +48,8 @@ dist-hook: gen-ChangeLog
 clean-local:
        rm -rf cache/
 
+CONFIG_STATUS_DEPENDENCIES = GUILE-VERSION
+
 gen_start_rev = 61db429e251bfd2f75cb4632972e0238056eb24b
 .PHONY: gen-ChangeLog
 gen-ChangeLog:
diff --git a/doc/ref/api-debug.texi b/doc/ref/api-debug.texi
index 747ac45..37a5b21 100644
--- a/doc/ref/api-debug.texi
+++ b/doc/ref/api-debug.texi
@@ -256,6 +256,17 @@ If the @code{positions} reader option is enabled, each 
parenthesized
 expression will have values set for the @code{filename}, @code{line} and
 @code{column} properties.
 
+If you're stuck with defmacros (@pxref{Defmacros}), and want to preserve
+source information, the following helper function might be useful to
+you:
+
address@hidden {Scheme Procedure} cons-source xorig x y
address@hidden {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.
address@hidden deffn
+
 
 @node Starting a New Stack
 @subsubsection Starting a New Stack
diff --git a/doc/ref/api-macros.texi b/doc/ref/api-macros.texi
index bd81ba3..51f54ed 100644
--- a/doc/ref/api-macros.texi
+++ b/doc/ref/api-macros.texi
@@ -128,6 +128,10 @@ same @var{letrec-syntax}.
 a beauty worthy of Scheme.
 
 @deffn {Syntax} syntax-rules literals (pattern template)...
+Create a syntax transformer that will rewrite an expression using the rules
+embodied in the @var{pattern} and @var{template} clauses.
address@hidden deffn
+
 A @code{syntax-rules} macro consists of three parts: the literals (if any), the
 patterns, and as many templates as there are patterns.
 
@@ -135,7 +139,6 @@ When the syntax expander sees the invocation of a 
@code{syntax-rules} macro, it
 matches the expression against the patterns, in order, and rewrites the
 expression using the template from the first matching pattern. If no pattern
 matches, a syntax error is signalled.
address@hidden deffn
 
 @subsubsection Patterns
 
@@ -357,17 +360,322 @@ Primer for the Merely Eccentric}.
 @node Syntax Case
 @subsection Support for the @code{syntax-case} System
 
address@hidden macros are procedural syntax transformers, with a power
+worthy of Scheme.
+
address@hidden {Syntax} syntax-case syntax literals (pattern [guard] exp)...
+Match the syntax object @var{syntax} against the given patterns, in order. If a
address@hidden matches, return the result of evaluating the associated 
@var{exp}.
address@hidden deffn
+
+Compare the following definitions of @code{when}:
+
address@hidden
+(define-syntax when
+  (syntax-rules ()
+    ((_ test e e* ...)
+     (if test (begin e e* ...)))))
+
+(define-syntax when
+  (lambda (x)
+    (syntax-case x ()
+      ((_ test e e* ...)
+       #'(if test (begin e e* ...))))))
address@hidden example
+
+Clearly, the @code{syntax-case} definition is similar to its 
@code{syntax-rules}
+counterpart, and equally clearly there are some differences. The
address@hidden definition is wrapped in a @code{lambda}, a function of one
+argument; that argument is passed to the @code{syntax-case} invocation; and the
+``return value'' of the macro has a @code{#'} prefix.
+
+All of these differences stem from the fact that @code{syntax-case} does not
+define a syntax transformer itself -- instead, @code{syntax-case} expressions
+provide a way to destructure a @dfn{syntax object}, and to rebuild syntax
+objects as output.
+
+So the @code{lambda} wrapper is simply a leaky implementation detail, that
+syntax transformers are just functions that transform syntax to syntax. This
+should not be surprising, given that we have already described macros as
+``programs that write programs''. @code{syntax-case} is simply a way to take
+apart and put together program text, and to be a valid syntax transformer it
+needs to be wrapped in a procedure.
+
+Unlike traditional Lisp macros (@pxref{Defmacros}), @code{syntax-case} macros
+transform syntax objects, not raw Scheme forms. Recall the naive expansion of
address@hidden given in the previous section:
+
address@hidden
+(let ((t #t))
+  (my-or #f t))
+;; naive expansion:
+(let ((t #t))
+  (let ((t #f))
+    (if t t t)))
address@hidden example
+
+Raw Scheme forms simply don't have enough information to distinguish the first
+two @code{t} instances in @code{(if t t t)} from the third @code{t}. So instead
+of representing identifiers as symbols, the syntax expander represents
+identifiers as annotated syntax objects, attaching such information to those
+syntax objects as is needed to maintain referential transparency.
+
address@hidden {Syntax} syntax form
+Create a syntax object wrapping @var{form} within the current lexical context.
address@hidden deffn
+
+Syntax objects are typically created internally to the process of expansion, 
but
+it is possible to create them outside of syntax expansion:
+
address@hidden
+(syntax (foo bar baz))
address@hidden #<some representation of that syntax>
address@hidden example
+
address@hidden
+However it is more common, and useful, to create syntax objects when building
+output from a @code{syntax-case} expression.
+
address@hidden
+(define-syntax add1
+  (lambda (x)
+    (syntax-case x ()
+      ((_ exp)
+       (syntax (+ exp 1))))))
address@hidden example
+
+It is not strictly necessary for a @code{syntax-case} expression to return a
+syntax object, because @code{syntax-case} expressions can be used in helper
+functions, or otherwise used outside of syntax expansion itself. However a
+syntax transformer procedure  must return a syntax object, so most uses of
address@hidden do end up returning syntax objects.
+
+Here in this case, the form that built the return value was @code{(syntax (+ 
exp
+1))}. The interesting thing about this is that within a @code{syntax}
+expression, any appearance of a pattern variable is substitued into the
+resulting syntax object, carrying with it all relevant metadata from the source
+expression, such as lexical identity and source location.
+
+Indeed, a pattern variable may only be referenced from inside a @code{syntax}
+form. The syntax expander would raise an error when defining @code{add1} if it
+found @var{exp} referenced outside a @code{syntax} form.
+
+Since @code{syntax} appears frequently in macro-heavy code, it has a special
+reader macro: @code{#'}. @code{#'foo} is transformed by the reader into
address@hidden(syntax foo)}, just as @code{'foo} is tranformed into 
@code{(quote foo)}.
+
+The pattern language used by @code{syntax-case} is conveniently the same
+language used by @code{syntax-rules}. Given this, Guile actually defines
address@hidden in terms of @code{syntax-case}:
+
address@hidden
+(define-syntax syntax-rules
+  (lambda (x)
+    (syntax-case x ()
+      ((_ (k ...) ((keyword . pattern) template) ...)
+       #'(lambda (x)
+           (syntax-case x (k ...)
+             ((dummy . pattern) #'template)
+             ...))))))
address@hidden example
+
+And that's that.
+
address@hidden Why @code{syntax-case}?
+
+The examples we have shown thus far could just as well have been expressed with
address@hidden, and have just shown that @code{syntax-case} is more
+verbose, which is true. But there is a difference: @code{syntax-case} creates
address@hidden macros, giving the full power of Scheme to the macro expander.
+This has many practical applications.
+
+A common desire is to be able to match a form only if it is an identifier. This
+is impossible with @code{syntax-rules}, given the datum matching forms. But 
with
address@hidden it is easy:
+
address@hidden {Scheme Procedure} identifier? syntax-object
+Returns @code{#t} iff @var{syntax-object} is an identifier.
address@hidden deffn
+
address@hidden
+(define-syntax add1!
+  (lambda (x)
+    (syntax-case x ()
+      ((_ var) (identifier? #'var)
+       #'(set! var (add1 var))))))
+
+(define foo 0)
+(add1! foo)
+foo @result{} 1
+(add1! "not-an-identifier") @result{} error
address@hidden example
+
+With @code{syntax-rules}, the error for @code{(add1! "not-an-identifier")} 
would
+be something like ``invalid @code{set!}''. With @code{syntax-case}, it will say
+something like ``invalid @code{add1!}'', because we attach the @dfn{guard
+clause} to the pattern: @code{(identifier? #'var)}. This becomes more important
+with more complicated macros. It is necessary to use @code{identifier?}, 
because
+to the expander, an identifier is more than a bare symbol.
+
+Note that even in the guard clause, we reference the @var{var} pattern variable
+within a @code{syntax} form, via @code{#'var}.
+
+Another common desire is to introduce bindings into the lexical context of the
+output expression. One example would be in the so-called ``anaphoric macros'',
+like @code{aif}. Anaphoric macros bind some expression to a well-known
+identifier, often @code{it}, within their bodies. For example, in @code{(aif
+(foo) (bar it))}, @code{it} would be bound to the result of @code{(foo)}.
+
+To begin with, we should mention a solution that doesn't work:
+
address@hidden
+;; doesn't work
+(define-syntax aif
+  (lambda (x)
+    (syntax-case x ()
+      ((_ test then else)
+       #'(let ((it test))
+           (if it then else))))))
address@hidden example
+
+The reason that this doesn't work is that, by default, the expander will
+preserve referential transparency; the @var{then} and @var{else} expressions
+won't have access to the binding of @code{it}.
+
+But they can, if we explicitly introduce a binding via @code{datum->syntax}.
+
address@hidden {Scheme Procedure} datum->syntax for-syntax datum
+Create a syntax object that wraps @var{datum}, within the lexical context
+corresponding to the syntax object @var{for-syntax}.
address@hidden deffn
+
+For completeness, we should mention that it is possible to strip the metadata
+from a syntax object, returning a raw Scheme datum:
+
address@hidden {Scheme Procedure} syntax->datum syntax-object
+Strip the metadata from @var{syntax-object}, returning its contents as a raw
+Scheme datum.
address@hidden deffn
+
+In this case we want to introduce @code{it} in the context of the whole
+expression, so we can create a syntax object as @code{(datum->syntax x 'it)},
+where @code{x} is the whole expression, as passed to the transformer procedure.
+
+Here's another solution that doesn't work:
+
address@hidden
+;; doesn't work either
+(define-syntax aif
+  (lambda (x)
+    (syntax-case x ()
+      ((_ test then else)
+       (let ((it (datum->syntax x 'it)))
+         #'(let ((it test))
+             (if it then else)))))))
address@hidden example
+
+The reason that this one doesn't work is that there are really two environments
+at work here -- the environment of pattern variables, as bound by
address@hidden, and the environment of lexical variables, as bound by normal
+Scheme. Here we need to introduce a piece of Scheme's environment into that of
+the syntax expander, and we can do so using @code{syntax-case} itself:
+
address@hidden
+;; works, but is obtuse
+(define-syntax aif
+  (lambda (x)
+    (syntax-case x ()
+      ((_ test then else)
+       ;; invoking syntax-case on the generated
+       ;; syntax object to expose it to `syntax'
+       (syntax-case (datum->syntax x 'it) ()
+         (it
+           #'(let ((it test))
+               (if it then else))))))))
+
+(aif (getuid) (display it) (display "none")) (newline)
address@hidden 500
address@hidden example
+
+However there are easier ways to write this. @code{with-syntax} is often
+convenient:
+
address@hidden {Syntax} with-syntax ((pat val)...) exp...
+Bind patterns @var{pat} from their corresponding values @var{val}, within the
+lexical context of @var{exp...}.
+
address@hidden
+;; better
+(define-syntax aif
+  (lambda (x)
+    (syntax-case x ()
+      ((_ test then else)
+       (with-syntax ((it (datum->syntax x 'it)))
+         #'(let ((it test))
+             (if it then else)))))))
address@hidden example
address@hidden deffn
+
+As you might imagine, @code{with-syntax} is defined in terms of
address@hidden But even that might be off-putting to you if you are an old
+Lisp macro hacker, used to building macro output with @code{quasiquote}. The
+issue is that @code{with-syntax} creates a separation between the point of
+definition of a value and its point of substitution.
+
address@hidden quasisyntax
address@hidden unsyntax
address@hidden unsyntax-splicing
+So for cases in which a @code{quasiquote} style makes more sense,
address@hidden also defines @code{quasisyntax}, and the related
address@hidden and @code{unsyntax-splicing}, abbreviated by the reader as
address@hidden, @code{#,}, and @code{#,@@}, respectively.
+
+For example, to define a macro that inserts a compile-time timestamp into a
+source file, one may write:
+
address@hidden
+(define-syntax display-compile-timestamp
+  (lambda (x)
+    (syntax-case x ()
+      ((_)
+       #`(begin
+          (display "The compile timestamp was: ")
+          (display #,(current-time))
+          (newline))))))
address@hidden example
+
+Finally, we should mention the following helper procedures defined by the core
+of @code{syntax-case}:
+
address@hidden {Scheme Procedure} bound-identifier=? a b
+Returns @code{#t} iff the syntax objects @var{a} and @var{b} refer to the same
+lexically-bound identifier.
address@hidden deffn
+
address@hidden {Scheme Procedure} free-identifier=? a b
+Returns @code{#t} iff the syntax objects @var{a} and @var{b} refer to the same
+free identifier.
address@hidden deffn
+
address@hidden {Scheme Procedure} generate-temporaries ls
+Return a list of temporary identifiers as long as @var{ls} is long.
address@hidden deffn
+
+Readers interested in further information on @code{syntax-case} macros should
+see R. Kent Dybvig's excellent @cite{The Scheme Programming Language}, either
+edition 3 or 4, in the chapter on syntax. Dybvig was the primary author of the
address@hidden system. The book itself is available online at
address@hidden://scheme.com/tspl4/}.
+
 @node Defmacros
 @subsection Lisp-style Macro Definitions
 
-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
+The traditional way to define macros in Lisp 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 @code{define}.
 
 @fnindex defmacro
 @fnindex define-macro
@@ -390,67 +698,161 @@ is the same as
 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:
+Having read the previous section on @code{syntax-case}, it's probably clear 
that
+Guile actually implements defmacros in terms of @code{syntax-case}, applying 
the
+transformer on the expression between invocations of @code{syntax->datum} and
address@hidden>syntax}. This realization leads us to the problem with defmacros,
+that they do not preserve referential transparency. One can be careful to not
+introduce bindings into expanded code, via liberal use of @code{gensym}, but
+there is no getting around the lack of referential transparency for free
+bindings in the macro itself.
 
address@hidden
-(defmacro false-if-exception (expr)
-  `(catch #t
-          (lambda () ,expr)
-          (lambda args #f)))
address@hidden lisp
+Even a macro as simple as our @code{when} from before is difficult to get 
right:
 
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
+(define-macro (when cond exp . rest)
+  `(if ,cond
+       (begin ,exp . ,rest)))
 
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
+(when #f (display "Launching missiles!\n"))
address@hidden #f
 
address@hidden {Scheme Procedure} cons-source xorig x y
address@hidden {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.
address@hidden deffn
+(let ((if list))
+  (when #f (display "Launching missiles!\n")))
address@hidden Launching missiles!
address@hidden (#f #<unspecified>)
address@hidden example
+
+Guile's perspective is that defmacros have had a good run, but that modern
+macros should be written with @code{syntax-rules} or @code{syntax-case}. There
+are still many uses of defmacros within Guile itself, but we will be phasing
+them out over time. Of course we won't take away @code{defmacro} or
address@hidden themselves, as there is lots of code out there that uses
+them.
 
 
 @node Identifier Macros
 @subsection Identifier Macros
 
+When the syntax expander sees a form in which the first element is a macro, the
+whole form gets passed to the macro's syntax transformer. One may visualize 
this
+as:
+
address@hidden
+(define-syntax foo foo-transformer)
+(foo @var{arg}...)
+;; expands via
+(foo-transformer #'(foo @var{arg}...))
address@hidden example
+
+If, on the other hand, a macro is referenced in some other part of a form, the
+syntax transformer is invoked with only the macro reference, not the whole 
form.
+
address@hidden
+(define-syntax foo foo-transformer)
+foo
+;; expands via
+(foo-transformer #'foo)
address@hidden example
+
+This allows bare identifier references to be replaced programmatically via a
+macro. @code{syntax-rules} provides some syntax to effect this transformation
+more easily.
+
address@hidden {Syntax} identifier-syntax exp
+Returns a macro transformer that will replace occurences of the macro with
address@hidden
address@hidden deffn
+
+For example, if you are importing external code written in terms of @code{fx+},
+the fixnum addition operator, but Guile doesn't have @code{fx+}, you may use 
the
+following to replace @code{fx+} with @code{+}:
+
address@hidden
+(define-syntax fx+ (identifier-syntax +))
address@hidden example
+
+Later versions of the @code{psyntax} @code{syntax-case} expander, on which
+Guile's syntax expander is based, include @code{identifier-syntax} support for
+recognizing identifiers on the left-hand side of a @code{set!} expression as
+well. Guile should port that code to its expander.
+
 @node Eval When
 @subsection Eval-when
 
address@hidden Internal Macros
address@hidden Internal Macros
+As @code{syntax-case} macros have the whole power of Scheme available to them,
+they present a problem regarding time: when a macro runs, what parts of the
+program are available for the macro to use?
+
+The default answer to this question is that when you import a module (via
address@hidden or @code{use-modules}), that module will be loaded up at
+expansion-time, as well as at run-time. Additionally, top-level syntactic
+definitions within one compilation unit made by @code{define-syntax} are also
+evaluated at expansion time, in the order that they appear in the compilation
+unit (file).
+
+But if a syntactic definition needs to call out to a normal procedure at
+expansion-time, it might well need need special declarations to indicate that
+the procedure should be made available at expansion-time.
+
+For example, the following code will work at a REPL, but not in a file:
+
address@hidden
+;; incorrect
+(use-modules (srfi srfi-19))
+(define (date) (date->string (current-date)))
+(define-syntax %date (identifier-syntax (date)))
+(define *compilation-date* %date)
address@hidden example
+
+It works at a REPL because the expressions are evaluated one-by-one, in order,
+but if placed in a file, the expressions are expanded one-by-one, but not
+evaluated until the compiled file is loaded.
+
+The fix is to use @code{eval-when}.
 
address@hidden
+;; correct: using eval-when
+(use-modules (srfi srfi-19))
+(eval-when (compile load eval)
+  (define (date) (date->string (current-date))))
+(define-syntax %date (identifier-syntax (date)))
+(define *compilation-date* %date)
address@hidden example
 
-Internally, Guile represents macros using a disjoint type.
address@hidden {Syntax} eval-when conditions exp...
+Evaluate @var{exp...} under the given @var{conditions}. Valid conditions 
include
address@hidden, @code{load}, and @code{compile}. If you need to use
address@hidden, use it with all three conditions, as in the above example.
+Other uses of @code{eval-when} may void your warranty or poison your cat.
address@hidden deffn
+
address@hidden Internal Macros
address@hidden Internal Macros
 
 @deffn {Scheme Procedure} make-syntax-transformer name type binding
+Construct a syntax transformer object. This is part of Guile's low-level 
support
+for syntax-case.
 @end deffn
 
 @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, a
-syntax transformer, or a syntax-case macro.
+Return @code{#t} iff @var{obj} is a syntax transformer.
+
+Note that it's a bit difficult to actually get a macro as a first-class object;
+simply naming it (like @code{case}) will produce a syntax error. But it is
+possible to get these objects using @code{module-ref}:
+
address@hidden
+(macro? (module-ref (current-module) 'case))
address@hidden #t
address@hidden example
 @end deffn
 
 @deffn {Scheme Procedure} macro-type m
 @deffnx {C Function} scm_macro_type (m)
-Return one of the symbols @code{syntax}, @code{macro},
address@hidden, or @code{syntax-case}, depending on whether
address@hidden is a syntax transformer, a regular macro, a memoizing
-macro, or a syntax-case macro, respectively.  If @var{m} is
-not a macro, @code{#f} is returned.
+Return the @var{type} that was given when @var{m} was constructed, via
address@hidden
 @end deffn
 
 @deffn {Scheme Procedure} macro-name m
@@ -458,16 +860,18 @@ not a macro, @code{#f} is returned.
 Return the name of the macro @var{m}.
 @end deffn
 
address@hidden {Scheme Procedure} macro-transformer m
address@hidden {C Function} scm_macro_transformer (m)
-Return the transformer of the macro @var{m}.
address@hidden deffn
-
 @deffn {Scheme Procedure} macro-binding m
 @deffnx {C Function} scm_macro_binding (m)
 Return the binding of the macro @var{m}.
 @end deffn
 
address@hidden {Scheme Procedure} macro-transformer m
address@hidden {C Function} scm_macro_transformer (m)
+Return the transformer of the macro @var{m}. This will return a procedure, for
+which one may ask the docstring. That's the whole reason this section is
+documented. Actually a part of the result of @code{macro-binding}.
address@hidden deffn
+
 
 @c Local Variables:
 @c TeX-master: "guile.texi"


hooks/post-receive
-- 
GNU Guile




reply via email to

[Prev in Thread] Current Thread [Next in Thread]