From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Ian Price Newsgroups: gmane.lisp.guile.devel Subject: Re: Syntax Parameters documentation for guile Date: Tue, 03 Jan 2012 23:04:30 +0000 Message-ID: <87sjjwz8u9.fsf@Kagami.home> References: <87pqff8f5g.fsf@Kagami.home> <20222.48501.219043.125940@winooski.ccs.neu.edu> NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: dough.gmane.org 1325632223 18062 80.91.229.12 (3 Jan 2012 23:10:23 GMT) X-Complaints-To: usenet@dough.gmane.org NNTP-Posting-Date: Tue, 3 Jan 2012 23:10:23 +0000 (UTC) Cc: Guile Mailing List To: Eli Barzilay Original-X-From: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Wed Jan 04 00:10:19 2012 Return-path: Envelope-to: guile-devel@m.gmane.org Original-Received: from lists.gnu.org ([140.186.70.17]) by lo.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1RiDUo-0004cP-Hb for guile-devel@m.gmane.org; Wed, 04 Jan 2012 00:10:18 +0100 Original-Received: from localhost ([::1]:44401 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RiDUn-0001CR-HF for guile-devel@m.gmane.org; Tue, 03 Jan 2012 18:10:17 -0500 Original-Received: from eggs.gnu.org ([140.186.70.92]:54284) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RiDUj-0001CA-Nw for guile-devel@gnu.org; Tue, 03 Jan 2012 18:10:15 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RiDUi-00075B-5E for guile-devel@gnu.org; Tue, 03 Jan 2012 18:10:13 -0500 Original-Received: from mail-we0-f169.google.com ([74.125.82.169]:59432) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RiDUh-000753-Op for guile-devel@gnu.org; Tue, 03 Jan 2012 18:10:12 -0500 Original-Received: by werf1 with SMTP id f1so10810087wer.0 for ; Tue, 03 Jan 2012 15:10:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlemail.com; s=gamma; h=from:to:cc:subject:references:date:in-reply-to:message-id :user-agent:mime-version:content-type; bh=H7hwiXtvgYKRFiEGuzMa0Vdu0pzLz0oUSQya8JAtuGE=; b=GgJ/7qTkrGtHVg9tmxCPh8QEPSEI2L9Y7AA9M1McBCjWkMOXJ5jT23/CxGzaL72Z5I 7aJjGfZRqANirzhHAp8zGW6zfsAi9vgVK25AtCH4DW8VXYdnUzovQpxVXXAqMwMaozGB wdsOdfSt2aeiDJi/Dm/WrY2ARM/Yv86MCxh7U= Original-Received: by 10.216.139.94 with SMTP id b72mr29994816wej.38.1325632209054; Tue, 03 Jan 2012 15:10:09 -0800 (PST) Original-Received: from Kagami.home (host86-180-111-172.range86-180.btcentralplus.com. [86.180.111.172]) by mx.google.com with ESMTPS id ej17sm56828134wbb.14.2012.01.03.15.10.06 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 03 Jan 2012 15:10:07 -0800 (PST) In-Reply-To: <20222.48501.219043.125940@winooski.ccs.neu.edu> (Eli Barzilay's message of "Sat, 31 Dec 2011 02:44:53 -0500") User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.3 (gnu/linux) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 2) X-Received-From: 74.125.82.169 X-BeenThere: guile-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Developers list for Guile, the GNU extensibility library" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Original-Sender: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.lisp.guile.devel:13245 Archived-At: Eli Barzilay 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"