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

Re: RE: how expressive are they?



At 04:24 PM 11/25/2002, Paul Graham wrote:
>This reminds me of something that might be a good example 
>of macro power: generalized variables.  This swap is a 
>special case of CL rotatef, which in turn depends on setf, 
>which is a macro.  Can you write setf in Smalltalk?
>
>If it's argued that setf is part of the language, not 
>something users would write, the point is, a user *could*
>write it.  That is probably where most of the predefined
>Lisp macros came from.  It's only natural that many of the
>best macros you could write in Lisp are already part of 
>CL, considering all the years of macro hacking that preceded 
>the standard.

In fact, before Common Lisp, macros were the only way to write portable code.
I remember Drew McDermott had is own version of Lisp that you'd port to run on yours if you were reading his book,  and that an early Winston and Horn book used a very basic form of Lisp in order to stay "portable".  Common Lisp let you read most of most peoples code, but still allowed for language freedom.

>Just as the ultimate test of an good police force is that
>it never has to do anything, the ultimate measure of an
>extensible language may be that you never have to extend
>it, because all the good general-purpose extensions have
>already been thought of and incorporated into the standard.
>
>--pg
>
>--Anton van Straaten wrote:
>> Dan Weinreb wrote:
>> > I don't think we're going to make much progress talking about small
>> > examples like IF and :ifNotNil or whatever.  Macros are a heavy-duty
>> > tool for heavy-duty jobs.
>> 
>> While we have taken the 'if' example about as far as it will go, I see
>> macros as a wide-spectrum tool for a wide variety of jobs, small and large.
>> Paul Graham made the point earlier that macros are useful for a language
>> designer, in that they allow syntax to be easily built on top of a small
>> core language.  Having developed an abstraction for syntactic transformation
>> that proves useful to the language designer, it seems as though it might
>> prove useful to other developers, too.
>> 
>> An example of a small macro which illustrates something that may not be
>> possible otherwise - and which might be used in more complex scenarios - is
>> an operation to swap the values of two variables.  For example, Scheme
>> doesn't have such a feature, but a macro for it takes a few lines:
>> 
>> (define-syntax swap
>>   (syntax-rules ()
>>     ((swap x y)
>>      (let ((tmp x))
>>        (set! x y)
>>        (set! y tmp)))))
>> 
>> Now it's possible to use (swap a b) to swap the values of two variables.
>> 
>> Succinct closures don't help here, and nor does "easy syntax for
>> assignment", except in the sense that you could forget about the macro and
>> just write the code inline.  In a language that doesn't support call by
>> reference, a swap would be impractical or impossible without macros.  In
>> Smalltalk, for example, it may not be directly possible (?)  Someone seems
>> to have supported this by implementing "reified variables":
>> http://wiki.cs.uiuc.edu/VisualWorks/Reified+Variables - but there's a *lot*
>> of code to support it (420-odd lines, although it supports more than just
>> swapping variable values).  Perhaps Smalltalk could use a macro system? ;)
>> 
>> The swap example also illustrates a point I made earlier about encapsulation
>> in interfaces.  In C, swap can be implemented as a function which takes two
>> pointers, e.g. swap(&a, &b).  But why do we need to require that the user
>> pass through pointers?  It's implicit in the contract of the swap operation
>> that it modifies the values of the specified variables.  C++ addresses this
>> by adding reference parameters - piling on yet another specific language
>> feature.
>> 
>> This illustrates one of the things macros are particularly good at -
>> constructing a "language feature" that the host language doesn't already
>> have, and doing so in a way that doesn't require contortions on the part of
>> the caller.
>> 
>> It's impossible for language designers to predict every possible application
>> of their languages, but by providing macros, the designer acknowledges that,
>> and allows the user to implement what they need - and perhaps as
>> importantly, leave out what they don't need.
>> 
>> Scheme is perhaps the best example of this approach, because of how small
>> the core language is, and how sophisticated the constructs that can be built
>> with it are.  It makes an excellent language experimentation toolkit.  The
>> fact that Scheme doesn't have a module system, or an object system, is not
>> an obstacle, in theory - you can build them yourself, and quite a number
>> have of course been built.
>> 
>> This also allows the developer to choose subsystems with a balance of
>> features appropriate to their problem.  While other languages might not wish
>> to emulate Scheme's minimalism, the general idea that it's possible to make
>> some of the most basic characteristics of a language tunable is worthy of
>> consideration.
>> 
>> Languages that have more syntax, and built-in object systems, built-in
>> module systems, call-by-reference, etc. may have less need for macros, but
>> not having macros at all definitely closes off some possibilities.  If one
>> of a language's goals is to provide maximum flexibility to the developer,
>> macros are an important feature.  There's a lot to be said for not
>> attempting to provide every imaginable feature in a language, especially if
>> the language makes it easy to implement specialized features.
>> 
>> Anton
>>