On Wed, 2009-05-27 at 02:26 +0300, Abdulaziz Ghuloum wrote:
On May 27, 2009, at 1:59 AM, Eduardo Cavazos wrote:
>
> > Yow. Is this a bug? Whadami missing? Can any of y'all reproduce?
>
> It's a combination of a bug in Ikarus's REPL, and a bug in the R6RS
> version of SRFI 26.
>
> Basically, every time you use an unbound identifier in the repl,
> ikarus considers it "defined" as a variable. So, using <> the
> first time is as if proceeded by (define <>).
>
> So, what happens when you do the following two in sequence:
>
> > (define <>)
> > (import (srfi :26))
> > (cut / <> <>)
>
> The <> refers to the repl variable, so, it won't match as a the
> <> literal that cut recognizes (which is the unbound <>). So,
> regardless of whether ikarus's bug is fixed, the repl behavior
> would still be fragile. SRFI 26 should, instead, bind and export
> the two auxiliary keywords <> and <...> so that they override any
> bindings with the same name already existing in the repl.
I don't like R6RS's auxiliary keywords because it doesn't seem right to
export keywords which are local to the mini-language of particular
macros. IIUC, the justification is to prevent confusion when some
top-level defined or imported identifier is symbolically equal to an
identifier in a macro use which needs to be distinguished as a literal
keyword or a binding reference. E.g.:
(library (A)
(export else)
(import (rnrs)) ;; Pretend else is not exported from (rnrs).
(define else #F))
(import (rnrs) (A)) ;; Pretend else is not exported from (rnrs).
(cond ((not #T) 1) (else 2)) ;; Confusion: else is not what was assumed.
But exporting auxiliary keywords can only help prevent confusion for the
top-level case, and it cannot help in general for the equally likely
cases such as:
(let (---)
---
(define else #F)
---
(---
(---
(---
(cond ((not #T) 1) (else 2)) ;; Same confusion, but no protection.
---))
---)
---) ;; BTW, lots of --- means it's buried :)
So I don't think exporting auxiliary keywords is actually helping, it's
giving a superficial sense of protection. So what's the point of the
clutter and tedium of exporting and making auxiliary keywords?
Also, auxiliary keywords are only relevant for macros which need to
distinguish literals from references (e.g. cond, case, and cut). But
for many macros this need doesn't exist, and so free-identifier=? (and
therefore syntax-rules and syntax-case literals list) does not seem
appropriate. Instead, symbolic-identifier=? seems more appropriate.
And so it doesn't seem right to me that, e.g., all the
define-record-type local keywords are exported as auxiliary keywords,
because there's no possibility of conflict about them. E.g., this does
not work:
(let ((fields 1))
(define-record-type t (fields x))
'expression)
But who cares if fields is bound in the scope? I intentionally made my
matcher's local keywords recognized via symbolic-identifier=? so as to
not artificially restrict the set of allowable names of bindings which
can be in scope around uses of my matcher macros.
Plus, R6RS provides no standard way to make new auxiliary keywords.
Though, it's easy to do yourself:
(library (acme aux)
(export define-auxiliary-keyword)
(import (rnrs))
(define-syntax define-auxiliary-keyword
(syntax-rules ()
((_ name)
(define-syntax name
(lambda (stx)
(syntax-violation
'name "incorrect usage of auxiliary keyword" stx)))))))
So, I'm undecided whether (srfi :26 cut), or any library, should export
auxiliary keywords. I don't want to because it doesn't make sense to
me, but maybe I'm missing something.
--
: Derick
----------------------------------------------------------------