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

Re: Using Macros in Lisp



Reply to Tom McDougal:

   Spoken like a true Common Lisp man. :-) I'm a Scheme fan myself,
   not usually interested in using all the bells and whistles the
   committee crammed into Common Lisp.  Even w/ a memory as feeble
   as mine, there is something wrong when I have to look in the
   reference manual to understand my own code because I made use of
   some obscure albeit appropriate feature.

But after a while, after you've used the features a few times, 
knowing what to use and when to use it will become second nature.
I don't consider a language that is so small that you have to 
implement everything yourself all the time to be particularly
useful.

	I do not know how I would have found out about CHECK-TYPE 
	or ASSERT w/out the aid of this group, since requests to
	the local CL hackers failed to turn up either of them.

Though the Steele manual may be difficult to get through, depending
on how much experience you have programming, almost everything is 
there.  Certainly, there is far more there than it seems you have
found in Common Lisp.  There are also alot of issues covered which
you may not care about (at this point) but if one establishes an
attitude that Common Lisp is a "good thing" rather than a "bad thing"
(crammed with unuseful features by a "committe"), then you might
start to see the elegance.

Non-directed flame:
[It seems to be rather trendy these days to bash the CL comittee
for making a language that's "too big".  Sure there are problems 
with CL but if you take a good look at the language, you'll see 
that for the most part it is pretty well thought out. And considering
the level of semantics it deals with, comparing it with that bracketed
assembler language is a joke. If most of the CL bashers were more
interested in understanding the issues than justifying their own
ignorance, they'd be writing smaller and more efficient programs.]

	Certainly not.  By the same token, there's no need for lots of CL
	features that can be got at via more primitive functions.  It's a
	matter of providing a convenient syntax.  But that's a major
	reason we use macros, isn't it?

There really is little redundancy in CL, and basically, the way the 
language is designed, it doesn't make for a bigger language than you'd
have to implement to get comparable features.  The generic sequence functions,
for example, do not consitute a large amount of reduncancy over support for
things like assoc, etc.  I'm not being clear here... this is why I think
that Lisp is big:

There are alot of features in CL that many people might not
use because they don't fit into their own understanding of
computation or they're just not useful to them.

Solutions:

-  Develop code-analysis (tree-shaking) tools to help reduce
   the size of a final application image... this is NOT EASY,
   but it is somewhat promising

-  Make people aware of what is supported well in the language.
   If someone hand-codes their own loop a hundred times in their
   application, you can be sure you'll have an application image
   that's larger than if you called FIND.  In many cases, the 
   compiler should be able to optimize the call so that the cost
   difference for the call is negligible.  Often, in FIND, the inner
   loop can be faster.

	Am I getting flamed here?  Sorry!  I do not flatter myself that
	anyone else will want to look at most of my code.  In general,
	however, I agree with you.  I use a minimum of macros, I stick
	close to vanilla Common Lisp As I Know It (clearly a limited
	subset of the entire language :-), and document heavily, because
	when I come back to my code months later it's not easy to
	remember what I was thinking and what macros it relied on.

Sorry if it sounded like a flame.  It wasn't.  The point was that
application source code is not an appropriate battleground for
stylistic (personal) differences.  To obscure a language because one
thinks one has a better way to say it accomplishes nothing, unless he/she
is willing to fully develop the idea and submit it to X3J13.

It is far more responsible to build up the integrity of the language
by identifying its weak points and adding meaninful features than it is
to isolate oneself becuase of an asthetic conviction.

	This interests me from the (opposing?) points of view of style
	and compiler efficiency.  Stylistically, I try to avoid side-
	effects.  The above looks like C or Pascal translated into CL.  I
	also always wondered what SETQ looks like at the machine-level.
	Is it really very efficient?

Depending on the processor and the compiler, this can turn into a few
instructions, one instruction, or no instructions.  Since the variable
being set is a local, if the machine has enough general registers (i.e.
they can hold a lisp object), the storage of the result in the local
can be implicit in the multiply instruction (i.e. the destination register).

There are many more elaborate issues here for different architectures,
but basically, setting a local variable is just about the cheapest thing
you can do.  

Your question raises an interesting point.  SETQ on a local variable is
rather different in the sense of being a side effect (from a performance
point of view), since updating local variables can be as fast as value
passing (i.e. implicit in the control thread).  However, updating outside
the current lexical scope is usually quite a bit less efficient.

As far as avoiding side effects, I think that you're right: it is better
to aim toward a value passing approach in your programs, but when it's
clear that side effects are more efficient, don't be afraid do it.  That's
what SPECIAL is in CL for.  Remember, pushing arguments for a function call
takes time.  Passing a value through N nested function calls can become far more
expensive than a global variable reference when N is big, if its only going to
be referenced by someone at the bottom of the thread.

-david