From: Ian Price <ianprice90@googlemail.com>
To: Eli Barzilay <eli@barzilay.org>
Cc: Guile Mailing List <guile-devel@gnu.org>
Subject: Re: Syntax Parameters documentation for guile
Date: Tue, 03 Jan 2012 23:04:30 +0000 [thread overview]
Message-ID: <87sjjwz8u9.fsf@Kagami.home> (raw)
In-Reply-To: <20222.48501.219043.125940@winooski.ccs.neu.edu> (Eli Barzilay's message of "Sat, 31 Dec 2011 02:44:53 -0500")
Eli Barzilay <eli@barzilay.org> writes:
>> Syntax parameters[fn:1] are a mechanism for rebinding a macro
>> definition within the dynamic extent of a macro expansion. It
>> provides a convenient solution to one of the most common types of
>> unhygienic macro: those that introduce a special binding each time
>
> I'd explicitly say "unhygienic" here rather than "special".
Good point, I've changed it.
>> the macro is used. Examples include an 'if' form that binds the
>> result of the test to an 'it' binding, or class macros that
>> introduce a special 'self' binding.
>
> The `abort' example is also popular, probably even more than `it'. I
> think that there are practical uses of that (eg, a function with a
> `return' keyword), whereas anaphoric conditionals are more of an
> academic exercise that I don't think gets used in practice (at least
> in Schemes).
I mentioned it mostly because it is a traditional example, but I've
swapped it for the lambda with return.
I'm not sure how popular aif is in general (I prefer a clojure style
if-let), but I do know it is in the popular miscmacros egg for chicken.
>> is preserved. This is similar to the dynamic binding mechanisms we
>> have at run-time like parameters[fn:2] or fluids[fn:3].
>
> An important note to add here is that there is no "dynamic scope" in
> the usual sense here -- it's rather a dynamic scope during macro
> expansion, and for macro-bound identifiers. The resulting expanded
> code is of course as lexical as always. (We've had some discussions
> at #scheme where this was a confusing point.)
Ok, I've cleared this up.
>> ** define-syntax-parameter keyword transformer [syntax]
>> Binds keyword to the value obtained by evaluating transformer as a
>> syntax-parameter.
>
> The keyword is bound to the value of the `transformer' expression.
> (Evaluated at the syntax level, in Racket's case, I don't know if
> Guile has separate phases yet...) It's not evaluated as a syntax
> parameter, just like parameters.
This is a case of syntactic ambiguity in English, I meant it as
"Binds keyword to (the value obtained by evaluating transformer) as a
syntax-parameter."
I've just dropped the "as a syntax-parameter" part.
>> The transformer provides the default expansion for the syntax
>> parameter, and in the absence of syntax-parameterize, is
>> functionally equivalent to define-syntax.
>
> A good note to add here is that it is usually bound to a transformer
> that throws a syntax error like "`foo' must be used inside a `bar'".
> It immediately clarifies the use of syntax parameters in the common
> case.
Done. I've also added an example that does this.
>> ** syntax-parameterize ((keyword transformer) ...) exp ... [syntax]
>> (note, each keyword must be bound to a syntax-parameter
>>
>> Adjusts each of the keywords to use the value obtained by evaluating
>> their respective transformer, in the expansion of the exp forms. It
>> differs from let-syntax, in that the binding is not shadowed, but
>> adjusted, and so uses of the keyword in the expansion of exp forms
>> use the new transformers.
>
> A possibly useful analogy is with `fluid-let' which doesn't create new
> bindings, but rather `set!'s them. But IMO `fluid-let' should die, so
> using parameters is a better example...
I've made the comparison with regular parameters more explicit.
Thanks a lot, Eli.
In case anyone else has any comments, the modified version is included
below. Now I'm off to learn about texinfo :)
* Syntax Parameters
Syntax parameters[fn:1] are a mechanism for rebinding a macro
definition within the dynamic extent of a macro expansion. It 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 'lambda' form with a 'return' keyword , or
class macros that introduce a special '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 like parameters[fn:2] or fluids[fn:3], except that the
dynamic binding only occurs during macro expansion. The code after
macro expansion remains lexically scoped.
** define-syntax-parameter keyword transformer [syntax]
Binds keyword to the value obtained by evaluating transformer. The
transformer provides the default expansion for the syntax parameter,
and in the absence of syntax-parameterize, is functionally equivalent
to define-syntax. Usually, you will just want to have the transformer
throw a syntax error indicating that the keyword is supposed to be
used in conjunction with another macro. (see example)
** syntax-parameterize ((keyword transformer) ...) exp ... [syntax]
Adjusts each of the keywords to use the value obtained by evaluating
their respective transformer, in the expansion of the exp forms. Each
keyword must be bound to a syntax-parameter. syntax-parameterize
differs from let-syntax, in that the binding is not shadowed, but
adjusted, and so uses of the keyword in the expansion of exp forms use
the new transformers. This is somewhat similar to how parameterize
adjusts the values of regular parameters, rather than creating new
bindings.
** example
A short example, showing how you can use syntax parameters to create a
variant of 'lambda' that allows early return from the function via the
'return' keyword.
#+begin_src scheme
(define-syntax-parameter return
;; by default we bind 'return' to a macro that merely raises a syntax error
(lambda (stx)
(syntax-violation 'return "return used outside of a lambda^" stx)))
(define-syntax lambda^
(syntax-rules ()
[(lambda^ argument-list body bodies ...)
(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
bodies ...))))]))
;; 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_src
* Footnotes
[fn:1] Eli Barzilay, Ryan Culpepper and Matthew Flatt. Keeping it
Clean with Syntax Parameters. In Proc. Workshop on Scheme and
Functional Programming, October 2011.
[fn:2] Marc Feeley. SRFI 39: Parameter objects, 2003.
http://srfi.schemers.org/srfi-39/.
[fn:3] https://www.gnu.org/software/guile/manual/guile.html#Fluids-and-Dynamic-States
--
Ian Price
"Programming is like pinball. The reward for doing it well is
the opportunity to do it again" - from "The Wizardy Compiled"
next prev parent reply other threads:[~2012-01-03 23:04 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-12-23 15:46 Syntax Parameters documentation for guile Ian Price
2011-12-31 7:44 ` Eli Barzilay
2012-01-03 23:04 ` Ian Price [this message]
2012-01-04 0:33 ` Eli Barzilay
2012-01-06 18:47 ` Andy Wingo
2012-01-07 2:05 ` Ian Price
2012-01-07 17:37 ` Ian Price
2012-01-08 0:06 ` Andy Wingo
2012-01-08 2:39 ` Ian Price
2012-01-08 13:47 ` Andy Wingo
2012-01-07 2:30 ` Eli Barzilay
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/guile/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87sjjwz8u9.fsf@Kagami.home \
--to=ianprice90@googlemail.com \
--cc=eli@barzilay.org \
--cc=guile-devel@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).