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

Re: [Scheme-reports] auxiliary syntax

On Sat, Jan 12, 2013 at 12:37 PM, Aaron W. Hsu <arcfide@x> wrote:
On Sat, 2013-01-12 at 11:48 +0900, Alex Shinn wrote:
> Rather, it's a type of low-level macro that looks at symbol names, and
> how we could potentially do the same thing with high-level macros.

Okay, I was holding off until now, but now I think I gotta say that this
has already been done and has existed in an usable state for a long time
now in Chez Scheme and probably elsewhere that uses the `syntax-case'

In particular, Chez extends 'syntax-rules' to allow for a guard clause
which allows one to unhygienically match against a literal if so

(define-syntax match-my-plus
  (syntax-rules ()
    [(_ plus) (eq? '+ (syntax->datum #'plus)) #t]
    [(_ else) #f]))

This will give true only in the case where we have (match-my-plus +) and
it will not return true for something like (let () (alias blah +)
(match-my-plus blah)).

I fail to see what the problem is here.

Sure, this works fine.  Again, it's a non-portable extension -
we left out guard clauses in the small language because they
introduce phasing issues, but I think they're a great feature and
we're likely to include them in the large language.

The macro was a concrete example of my general complaint,
which is mostly that people argue how important auxiliary
syntax is, and I think in many cases it's the wrong thing, e.g.
it can't be made to build macros on top of SREs.

Another example (from the same source, SCSH) is the `run'
syntax.  This is another symbol language where the symbols
refer to program names, and cannot be renamed or even
resolved until runtime.

Other cases are where you have a simple language which
just has a few names, in positions which could never conflict
with the lexical scope, basically keyword parameters.  For
example the R6RS-style record syntax, which uses some
common terms like `fields', `mutable' and `parent'.  It is not
the case that you would never want to extend this syntax,
but you're also not going to want arbitrary code in the operator
positions - these are very specific parameters which all need
to be understood and processed together by the define-record
macro.  If we extend them, we need to extend define-record
anyway, and it can be made to recognize the new names.

Now suppose we have a macro which defines database
tables, with similar keywords like `fields' and `mutable'.
If we want to use both of these in the same program, we
need to rename one or both.  Do you really want to have
to write:

  (define-record foo
    (record-fields ...)
    (record-parent ...)

when there's really no necessity, and matching literally
instead of hygienically would never break?

These are common names, but another issue is symbols
chosen for their appearance.  I've seen macros use =>,
<=, -> and <- often enough, and not being in the standard
the latter two are likely to conflict.  If someone wanted to
combine two macros using these should they have to use
`contract->' instead of `->' in Racket's contract language,
when the fact that it's a contract can be determined from

In some ways auxiliary keywords makes all of this worse.
If the binding were not provided by _either_ macro library,
they would match and you could use the original intended
name from both together without any renaming.  On the other
hand, renaming no longer becomes possible.

The point is to be aware that auxiliary syntax is not a silver
bullet, and that if you're using a macro system
which allows it there is a place for selective raw symbol
matching (though the macro itself _must_ be hygienic).
If you're just using a few keywords parameters or a DSL
which cannot be renamed or which is simply unambiguous
and doesn't need renaming, please consider raw symbol


Scheme-reports mailing list