From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Andreas Rottmann Newsgroups: gmane.lisp.guile.devel Subject: Re: hygiene and macro-introduced toplevel bindings Date: Mon, 28 Feb 2011 01:15:45 +0100 Message-ID: <87bp1xui8e.fsf@vir.lan> References: NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: text/plain X-Trace: dough.gmane.org 1298852180 1259 80.91.229.12 (28 Feb 2011 00:16:20 GMT) X-Complaints-To: usenet@dough.gmane.org NNTP-Posting-Date: Mon, 28 Feb 2011 00:16:20 +0000 (UTC) Cc: guile-devel To: Andy Wingo Original-X-From: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Mon Feb 28 01:16:14 2011 Return-path: Envelope-to: guile-devel@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1Ptqmb-00038M-RB for guile-devel@m.gmane.org; Mon, 28 Feb 2011 01:16:14 +0100 Original-Received: from localhost ([127.0.0.1]:59508 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Ptqmb-0006Ss-2m for guile-devel@m.gmane.org; Sun, 27 Feb 2011 19:16:13 -0500 Original-Received: from [140.186.70.92] (port=58066 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PtqmT-0006Sd-2P for guile-devel@gnu.org; Sun, 27 Feb 2011 19:16:10 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1PtqmN-0007T3-M5 for guile-devel@gnu.org; Sun, 27 Feb 2011 19:16:05 -0500 Original-Received: from mailout-de.gmx.net ([213.165.64.23]:54539) by eggs.gnu.org with smtp (Exim 4.71) (envelope-from ) id 1PtqmN-0007Sq-Ac for guile-devel@gnu.org; Sun, 27 Feb 2011 19:15:59 -0500 Original-Received: (qmail invoked by alias); 28 Feb 2011 00:15:56 -0000 Original-Received: from 83-215-154-5.hage.dyn.salzburg-online.at (EHLO nathot.lan) [83.215.154.5] by mail.gmx.net (mp061) with SMTP; 28 Feb 2011 01:15:56 +0100 X-Authenticated: #3102804 X-Provags-ID: V01U2FsdGVkX18v7dMfSx8vyfOziqEl9BU1fTaPmmcf/Tsi1oY8lD 2m55phDY2Xk0yt Original-Received: from localhost (localhost.localdomain [127.0.0.1]) by nathot.lan (Postfix) with ESMTP id 0BC6A3A68F; Mon, 28 Feb 2011 01:15:56 +0100 (CET) Original-Received: from nathot.lan ([127.0.0.1]) by localhost (nathot.lan [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id xef1LpniRygi; Mon, 28 Feb 2011 01:15:45 +0100 (CET) Original-Received: from vir (vir.lan [192.168.3.10]) by nathot.lan (Postfix) with ESMTP id A6CA53A685; Mon, 28 Feb 2011 01:15:45 +0100 (CET) Original-Received: by vir (Postfix, from userid 1000) id 5ED09BD9FB; Mon, 28 Feb 2011 01:15:45 +0100 (CET) In-Reply-To: (Andy Wingo's message of "Sun, 27 Feb 2011 22:37:42 +0100") User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.0.50 (gnu/linux) X-Y-GMX-Trusted: 0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 213.165.64.23 X-BeenThere: guile-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Developers list for Guile, the GNU extensibility library" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Errors-To: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.lisp.guile.devel:11726 Archived-At: Andy Wingo writes: > Hello all, > > Andreas has been struggling with a nonstandard behavior of Guile's > recently, and we should discuss it more directly. > > The issue is in expressions like this: > > (define-syntax define-accessor > (syntax-rules () > ((_ getter setter init) > (begin > (define val init) > (define getter (lambda () val)) > (define setter (lambda (x) (set! val x))) > > (define-accessor get-x set-x! 0) > This example serves to illustrate the issue, but I want to make clear that there are situations where one cannot work around "cleanly" around this issue -- in the above example, one could use `define-values' to define `setter' and `getter', and demote `val' into a `let' form inside the `define-values' expression -- when the `setter' and `getter' are macros, this is not possible. > The issue is, what happens when this expression is expanded? > > Within a let or a lambda, it expands to an three internal definitions: > `val', `getter', and `setter', where `val' is only visible to within the > `getter' and `setter' procedures. > > At the top level, it expands to three definitions: "val", the getter, > and the setter. However in this case the "val" binding is global to the > module, and can be referenced by anyone. > > This is what happens in Guile. I know that some other Schemes do > different things. Chez, as far as I understand it, binds "val" in the > module, but under a gensym'd name. It can do this because its modules > are syntactic: the bindings in a module are not serialized to disk as > simple symbol-binding pairs, but rather the whole expansion-time ribcage > is also written out. That's how I understand it anyway; I could be > getting things wrong there. > > Anyway, in Guile our modules have always been first-class entities. We > never intern gensym'd names in modules, because who would do that? You > put a name in a module because you want to be able to name it, either > internally or externally, and gensym'd names don't make any sense > without some sort of translation table, and Guile's first-class modules > have no such table. > Sorry, I don't understand the part about the translation table, could you clarify? I agree that it makes no sense to allocate a named binding in the module for `val', be it under a gensym'ed name, or just as `val'. The first is bad because of the cost, as you note below, and the latter is bad (worse, IMO) since it breaks encapsulation of the macro -- consider this: (define-accessor (get-foo set-foo! #f)) (define-accessor (get-bar set-bar! #f)) With the current psyntax implementation in Guile, this will lead to two definitions of `val' inside the same module. Ideally, Guile would allocate an "anonymous binding" inside the module -- a binding that has only a location, and lacking a visible name. I have a vague idea how to pull such a thing of: During each macro expansion, create a lexical environment, and put all hygeniencally renamed bindings (such as `val' in the above example) into that environment. For the above example, this would already be enough; the closures for `getter' and `setter' would refer to that environment, and so it's kept alive as long as those don't get undefined/redefined. If `getter' and `setter' were macros, one would have to put that environment in a slot in the macro transformer bindings. I know the above is quite hand-wavy, and I have actually no idea how difficult such a thing would be to implement, but it might be possible, even with first-level modules, to avoid the costs of gensym'd top-level bindings without breaking hygiene/encapsulation. I guess it would even be advantageous in terms of speed, as I guess lexical environment access is faster than referring to top-level bindings by name(?). > Furthermore, gensyms at the top-level have a cost that they do not have > lexically. When you introduce a lexical binding in a macro and cause a > new name to be allocated to it, that binding only exists within the > scope of that form -- if the form is an expression, it exists during the > dynamic extent of that expression, and if it is a definition, its extent > is bound to the extent of the binding of some /other/ name---the > top-level name. > > But when you introduce a generated name to the top-level, you create > some trash "val-12345543" binding which will always be there, and you > don't know why. It can never be removed by normal means, because > top-level bindings are never removed, and its name is invisible to all > other code -- it has infinite extent. > > And that's the thing that really bothers me about generated top-level > names: they are only acceptable if you plan on never changing your > mind. You're not bothered by the trash name, because you'll never > expand that expression again. > > So! That's my rant. But this is, even more than usual, a case in which > I could simply be wrong; so if you really want to defend generated > top-level names, now would be a great time to do so ;-) > Well, I'm not defending generated top-level names but arguing for preserving encapsulation/hygiene for macros ;-). I wonder what you (and others) think about my idea as outlined above -- could such a thing possibly work? Regards, Rotty -- Andreas Rottmann --