[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Date: Mon, 6 Apr 87 11:13:06 cdt
From: David Bartley <bartley%home%ti-csl.csnet at RELAY.CS.NET>
This appears to be more of a destructuring form than one restricted to
defining optional arguments. Would you allow the (OPTIONAL ...) to
appear anywhere or just directly inside a LAMBDA as its body? Must
the second "argument" (R) be the name of a "rest" arg?
It can appear anywhere, and R can be any list. In other words, it's
the obvious macro, nothing more or less, semantically at least.
(The syntax "(OPTIONAL r ((var default) ...) body)" is probably better than
"(OPTIONAL ((var default) ...) r body)".)
It apparently only allows destructuring at the top level of a list.
My use of the term "destructuring" was a little too free then. Your
proposal also only allows it at top level, yes? Mixing default
values with full destructuring would be awful...
My suggestion can also be implemented straightforwardly as a macro.
Into what would it expand? You would still need either (1) a
PRIMITIVE-LAMBDA expression type, (2) an incompatible LAMBDA in some
distinct syntax table, or (3) the ability to overload macros. I think
there are problems with all three approaches. I prefer the orthogonal
approach of giving distinct features distinct names.
(Well... why does LAMBDA support rest-arguments, you ask? And why does
the language have "named LET"? I remember that Dan Friedman argued
against overloading LAMBDA for n-ary procedures back in '84, for exactly
this reason. I vacillate between agreeing with him and not. I argued
against named LET, but other people said you can view unnamed LET as a
special case of named LET, therefore the overloading is OK, and
desirable because you want to minimize the number of reserved words at
almost any cost. They shouted more loudly, and won.)
I like this notation, but not the idea that its efficiency depends on
the cleverness of the compiler, since that inhibits using such
features in portable code. It would require a compiler to determine
whether the declared rest arg R were otherwise referenced from within
the body of the procedure in order to approach the efficiency a dumb
compiler could get with my approach.
As Alan Bawden asked, since when were efficiency considerations so
important in language design? However, I don't think OPTIONAL need be
inefficient. Sure, it needs a two-pass compiler, but given that,
detecting the situation is trivial, much easier than detecting whether a
LETREC is a loop or that an environment may be allocated on a stack or
in registers. I assume the PC Scheme compiler and most others are
already two-pass, so I don't think this is a big deal. I don't know of
anyone who is using a pure interpreter these days.
If you're concerned about the speed of portable code, I'd say this is
probably the least of your worries. Other kinds of unnecessary consing,
especially of environments, procedures, and continuations, will dominate
this kind if the compiler is only one-pass.
(But is it proper for one macro to assume that
another macro has not been redefined?)
The answer is no, if syntactic keywords are scoped at all (and they
ought to be) then it is definitely not proper, but that doesn't mean a
macro has no hope of examining subforms. Did you read my macro
proposal? You could deal with situations like this if there was some
way to examine preprocessed expressions. The ->CORE procedure in the
proposal would suffice if OPTIONAL-expressions were in its range.
But I think it would be better to put it in the compiler, especially
since the case without the rest-argument is the important one for error
checking. You don't want people to forego the error checking -- one
of the main reasons having an explicit optional-argument feature comes
up -- just in order to reduce consing, and you don't want macros doing
optimizations in any case.