Re: Scheme macros
From: Anton van Straaten (anton_at_appsolutions.com)
Date: 02/23/04
- Previous message: Kenny Tilton: "Re: Avoiding eval"
- In reply to: Brian Mastenbrook: "Re: Scheme macros"
- Next in thread: Brian Mastenbrook: "Re: Scheme macros"
- Reply: Brian Mastenbrook: "Re: Scheme macros"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: Mon, 23 Feb 2004 07:19:33 GMT
Brian Mastenbrook wrote:
> In article <mza_b.14958$W74.182@newsread1.news.atl.earthlink.net>,
> Anton van Straaten <anton@appsolutions.com> wrote:
>
> > I find that syntax-rules works very well for many kinds of
> > macros, better than defmacro in fact.
> >
> > Of course, the latter claim is hardly ever going to be accepted by
someone
> > only familiar with defmacro. For the record, I learned and used
defmacro
> > before ever using syntax-rules or syntax-case, and I still use defmacro
from
> > time to time, so I think I have a good basis for comparison.
>
> For the record, I'm familiar with both defmacro and syntax-rules,
> though I am considerably more familiar with the first. With helpful
> tools for list destructuring and mass generation of gensyms, defmacro
> macros can be pretty easy to write, whereas I often have to squint at a
> syntax-rules macro to figure out what ...'s correspond to what. Perhaps
> this is simply a consequence of my level of experience. Perhaps it's
> just personal preference.
I'm sure there is a large subjective element. My real point relates to the
initial reaction that defmacro users often have, to not knowing what's going
on when they don't see syntax and variables being quoted or unquoted.
However, this is actually a benefit of syntax-rules, that they're simply
unfamiliar with. I notice you didn't mention that issue as being something
that you have to squint for, which isn't surprising if you're somewhat
familiar with syntax-rules.
Re the ...'s, they since they appear after the expression which is being
repeated, I tend to think of them like a postfix token - along the lines of
the quote and quasiquote tokens, but appearing after the expression to which
it applies, instead of before. The equivalent operation in defmacro is
usually procedural code, which I don't think is any clearer to absorb at a
glance.
> I don't understand what makes GENSYM such a kludge, nor why it is such
> a low level of abstraction. GENSYM is not doing anything different than
> CONS does - it returns something which is unique to eq? with the
> specified contents. In CL, a GENSYM-alike can minimally be written as
> (make-symbol "").
Yes, GENSYM is just a constructor. But you don't normally have to
"construct" your variable names. The only reason you do with defmacro, is
because defmacro doesn't deal with hygiene. It's low-level because you're
implementing the sort of feature that is usually handled by the language.
You're right, that with some wrappers to generate gensym, you can make this
easier. But as I said, you don't have to do this with normal lexical or
other variables, and I doubt you'd be defending it if you did have to gensym
all your variables.
What makes macros different? That's semi-rhetorical - it's an interesting
question to answer. I think the answer ends up being that defmacro exists
at an intersection point between ease of implementation, sufficient ease of
use, and the macro equivalent of Turing-completeness. There are other
interesting intersection points, though.
> > All of the major Schemes either support continuations
> > well, or tell you when they don't - e.g., some of the Scheme to C
compilers
> > deliberately provide restricted continuations.
>
> Fortunately, this is what Chicken is for.
Yes, Chicken warms the cockles of my cool-hack-loving heart. For those who
aren't familiar, it's a Scheme which generates C code that uses a version of
Henry Baker's Cheney-on-the-MTA mechanism for supporting tail recursion and
continuations in C:
http://home.pipeline.com/~hbaker1/CheneyMTA.html )
> > For applications which need them, continuations
> > are very useful, and have little competition. Their competition is
mainly
> > OS-level threads, which really solve a different problem, and
conceptually
> > are a stream of continuations anyway.
>
> And here is where the next Lisp/Scheme debate is going to start up.
> When Schemers speak of continuations, they really mean implicit
> continuations - the idea that the program should be granted access to
> the continuations that are flying around under the hood in the
> implementation. However, the name "continuation" is considerably more
> general, or else anybody using CPS needs to find a new term.
No argument about the term. The full term for the Scheme thingies is
"first-class continuation", and you can produce them in other ways than
call/cc.
> In fact I would argue that the main competition to call/cc
> continuations is going to be CPS, and that CPS has a really big
> advantage: after you write your program, you can identify what types of
> continuations you use, and then change their representation to a list
> of a name and arguments which describes the continuation of that type.
CPS is very useful, but one of the applications for first-class
continuations is implementing language-level tools - exception systems,
unusual control flows like goal seeking, web server inversion of control,
etc. In all of these cases, you don't want to require the end programmer to
write their code in CPS. You raised that point:
> Of course this is all rather complicated to write by hand, but there is
> one huge advantage: the continuations are now serializable, even across
> different lisps! Provided with sufficient tools to generate code like
> this, I don't see why anyone would prefer call/cc continuations (which
> are inherently fragile) for this use case.
If you write tools to generate CPS code behind the scenes, so that the user
ends up with serializable continuations, then you've implemented a language
which offers first-class continuations. Whether it provides them through
call/cc or not isn't particularly important - call/cc just happens to be one
of the most simple and general way of giving access to continuations. If
such tools actually existed as a layer over Lisp or Scheme, I'm sure it
would be useful.
Those tools might still find it useful to offer something like call/cc, if
it's possible given the typing issues, so that users can do their own
control manipulations rather than relying on whatever the tools support. I
suspect it'll be tricky to eliminate the relevance of call/cc - it's a bit
like saying that given function definition syntax & variable binding syntax
etc., we could eliminate the need for lambda. It'd still be there, just
hidden, which is the way it's supposed to be anyway.
> One interesting thing to note is that continuations can be described in
> terms of the standard UNIX call fork() with shared memory. If you do
> use shared memory, fork() will simply copy the stack alone - so, to
> exploit this, when you call/cc, fork() a new process, and have it
> immediately suspend itself. When it is unsuspended, it should fork()
> itself into a running process and then re-suspend itself. When you call
> the associated continuation, unsuspend that process, and kill yourself.
> Make sure to store return values on the heap, and you're all set! Thus
> continuations are really a subset of standard UNIX multiprocessing
> semantics :-)
I presume you'd have to implement mutable variables via heap allocated ref
cells, or something, otherwise you'd end cloning variables that should be
shared (if I've understood the model correctly). So, since this model is
restricted, it's actually a subset of the continuation model, not the other
way around. :)
Anton
- Previous message: Kenny Tilton: "Re: Avoiding eval"
- In reply to: Brian Mastenbrook: "Re: Scheme macros"
- Next in thread: Brian Mastenbrook: "Re: Scheme macros"
- Reply: Brian Mastenbrook: "Re: Scheme macros"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]