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

Cost of R5RS macros (was: Fyi.)

   From: jar@cs.cornell.edu (Jonathan Rees)
   Date: Wed, 7 Apr 93 17:00:25 -0400

      I got no replies so I had to port syntactic
      closures myself.  I have since then asked if anyone had a macro
      package which didn't expand all the way down to primitive expressions
      and also got no replies.

   I don't know what you mean by "expand all the way down to primitive

What I mean is that the output from the macro-expand/renaming phase
has syntax only from section 4.1 Primitive expression types, namely:
Variable references, QUOTE, Procedure calls, LAMBDA, IF, and SET!,

All the derived expression types (COND, CASE, AND, OR, LET, LET*,
LETREC, DO, DELAY, and QUASIQUOTE) are turned into Primitive
expression types during the macro-expand/renaming phase.

   No, I agree on philosphical grounds, just not on practical grounds: I
   don't really understand your practical motivations for wanting an
   s-expression interpreter.

Because it is small and fast.  SCM runs as fast or faster (in
comparison with a C program on the same machine) than any other
interpreter implementation that I know of except for PC-SCHEME (which
is coded in assembly language).  Its interpreter doesn't need to have
a compiler to intermediate form and hence LOADs very quickly, making
it very nice to use for frequent reloading while debugging.

I know that conventional wisdom is that byte coded interpreters are
faster than direct interpreters, but it doesn't seem to be born out in

   (I feel like pointing out that the fact
   that you're passing the code through READ already constitutes an
   information-losing pre-pass.  If you're concerned about the
   information loss aspect of macro expansion, why not retain pointers to
   the source code *text*?  That would be much more useful for debugging,
   in any case...)

The PSD (portable scheme debugger) does just that.  When I need single
stepping I use PSD.  But my production code is not burdened with all
the overhead of that extra information.  The "information" I am
preserving by not expanding Section 4.2 Derived expression types gives
me a 30% speed increase.  It is done for that very practical reason.

      As for interleaving expansion with evaluation, that is what I
      tried to do, but I am having problems with internal defines.  In order
      to find out that a macro will return DEFINE or BEGIN of DEFINEs, I
      have to expand it before evaluation.  This requires an expansion
      prepass which replicates the environment tree ...

   Why does it have to replicate the environment tree?  You don't need to
   do recursive macro-expansion, only single-expression expansion.

Because the macro expansion which finally returns the DEFINE form
might be inside several layers of LET and LET-SYNTAXs.  Do I
misunderstand this?

      There is not much difference in the output from the macro expanders
      (syntax-case and syntactic closures) as they both output primitive
      scheme expressions.  The reason this slows down SCM execution 30% is
      that it doesn't allow SCM to execute the derived forms directly.

   Isn't that true of any macro system?

It is true that all macros get expanded.  But it is not neccessary
that all Section 4.2 Derived expression types be implemented as
macros.  Both SCM and the Hobbit compiler deal directly with Section
4.2 Derived expression types.  It would be nice to have macros which
preserve the Section 4.2 Derived expression types.  There is no
fundamental reason this couldn't be done; but as far as I know it has

   The objects that represent "generated names" in macro expansions do
   not need ot be symbols.  Neither Pseudoscheme no Scheme48 generates
   any extra symbols.

Good point!  I will look at creating a new, smaller type for the
generated symbols.