From: Breanndán Ó Nualláin
Subject: Q: Scheme style macro transformers in common lisp
Date: 
Message-ID: <s16hg4vj3e7.fsf@clause.wins.uva.nl>
Is there a common lisp implementation available of scheme style
define-syntax, let-syntax, letrec-syntax, syntax-rules, etc?

TIA,       ,
    Breanndan

From: David D. Lowry
Subject: Re: Q: Scheme style macro transformers in common lisp
Date: 
Message-ID: <3511297C.5F00@dbrc.com>
Breannd�n � Nuall�in wrote:
> 
> Is there a common lisp implementation available of scheme style
> define-syntax, let-syntax, letrec-syntax, syntax-rules, etc?
> 
> TIA,       ,
>     Breanndan

Well, there's DEFMACRO, similar to Scheme's define-syntax, and MACROLET,
which is either similar to let-syntax, or letrec-syntax.  I'm not sure
of the scoping rules for MACROLET, I think it's similar to let-syntax.

Be aware that Common Lisp Macros are not 'hygenic'.  This means you need
to be careful to avoid the variable capture problem.  Basically, if you
define variables (using LET etc.), in the body of your macro form, you
need to generate names for those variables using GENSYM.  Variable
capture bugs are pretty rare, but they're horrendous to debug.

DDL
From: Erik Naggum
Subject: Re: Q: Scheme style macro transformers in common lisp
Date: 
Message-ID: <3099315988158482@naggum.no>
* David D. Lowry
| Be aware that Common Lisp Macros are not 'hygenic'.

  what's the big deal about this purported hygiene?  sometimes, I _want_
  macros to be unhygienic, such as by introducing a macro into the name
  space of the body with a MACROLET (like LOOP-FINISH), and when I want to
  make sure that I don't pollute the environment, I use this simple macro:

(defmacro with-hygienic-variables (vars &body body)
  `(let ,(loop for var in vars collect
               `(,var (make-symbol ,(symbol-name var))))
     ,@body))

#:Erik
-- 
  religious cult update in light of new scientific discoveries:
  "when we cannot go to the comet, the comet must come to us."
From: Barry Margolin
Subject: Re: Q: Scheme style macro transformers in common lisp
Date: 
Message-ID: <1ncQ.4$fl.313253@cam-news-reader1.bbnplanet.com>
In article <················@naggum.no>, Erik Naggum  <······@naggum.no> wrote:
>  what's the big deal about this purported hygiene?  sometimes, I _want_
>  macros to be unhygienic, such as by introducing a macro into the name
>  space of the body with a MACROLET (like LOOP-FINISH), and when I want to
>  make sure that I don't pollute the environment, I use this simple macro:

While there are times you need to be unhygienic, most of the time you
don't.  So ideally the default should be hygienic, and you should have to
go out of your way when you need to override this.

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Cambridge, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
From: Kent M Pitman
Subject: Re: Q: Scheme style macro transformers in common lisp
Date: 
Message-ID: <sfwiupa3x5n.fsf@world.std.com>
Erik Naggum <······@naggum.no> writes:

> 
> * David D. Lowry
> | Be aware that Common Lisp Macros are not 'hygenic'.
> 
>   what's the big deal about this purported hygiene?  sometimes, I _want_
>   macros to be unhygienic, such as by introducing a macro into the name
>   space of the body with a MACROLET (like LOOP-FINISH), and when I want to
>   make sure that I don't pollute the environment, I use this simple macro:

I (and I think *only* I .. I feel somewhat lonely on the subject from
time to time) have argued that the desire for hygiene is antagonized in
Lisp1 dialects by the likelihood of tripping over names.  In a LispN
and ESPECIALLY a LispN with packages (rather than semantic modules sharing
eq symbols whose names are distinguishable only by the lexical contour),
it's easy to adopt a set of programming practices that keep you from having
to care about hygiene.  The following standard practices lead to a
situation that indeed explain why Lisp programmers rarely see a need for
hygiene when Scheme programmers can't see living without it.  The feel of
uncertainty Scheme programmers have in CL is mostly imagined and due to 
the fact that they are applying Scheme intuitions in a world they don't 
understand at a gut level--in effect, they are being paranoid.  But the
enemy they fear is real in the world they came from, so it's completely
understandable.

 #1: Most CL users don't make heavy use of FLET or LABELS
     and when they do they mostly don't make use of any name 
     that is also a global name. 

 #2: Most macros refer only to free functions and never to
     free variables.

     The only exceptions in what I'd call "good code"
     are where the writer has universally quantified over all code to
     make sure there are no conflicts, either by adopting a published
     convention (e.g., "certain macros will use names starting with $,
     so other code must not")  or by lexically binding the macro as a
     macrolet so that all the possible uses are apparent.

As a consequence, user programs can bind pretty much any variable and not
worry macros will collide.  It's an unwritten rule (partly forced by
lack of any kind of progv equivalent for functions) that functional args
will be received in variables, and so variables are the "fast and loose"
glue of the CL language.  If macros never rely on variables (other than
specials; which are special anyway because their meaning remains constant
even when re-bound) to have any particular magic value, and they always
rely on functions to be, in effect, constant, then macros are automatically
hygeinic.

The relationship between multiple namespaces and macro hygiene is one of
those subtle things that is almost an issue of "sociology" and tends to
get overlooked by computer scientists who think that everything about
a programming language can be reduced to its semantics.  But I allege
that the practical consequence of what I've said above is that there
is a symbiosis between LispN and non-hygienic macro systems that is quite
a lot healthier than it looks on paper to the theorists.

But whenver I think about Lisp1 vs Lisp2, I always remind myself of the
quote:

  There are two kinds of people in the world:
  people who think there are two kinds of people and people who don't.

To me, the war between Lisp1 and Lisp2 has never been about whether 1 or 2
was better, but whether "conformance to an arbitrary choice (1 being the
canonical arbitrary choice :)" was better than "tolerance".  And when you
admit that tolerance is better, you have to both recognize Lisp2 is ok
AND recognize Lisp1 is ok.  That is, you have to be "pro-choice".  And if
you think Lisp1 is ok, you have to acknowledge that hygiene IS necessary
to those who choose Lisp1.

The only thing that's not reasonable is for the Lisp1 people to wander into
a Lisp2 camp and insist that it's still necessary.  People need to know
whose playground they're playing in.

> (defmacro with-hygienic-variables (vars &body body)
>   `(let ,(loop for var in vars collect
>                `(,var (make-symbol ,(symbol-name var))))
>      ,@body))

FWIW, Harlequin LispWorks comes with this built-in.
We call it WITH-UNIQUE-NAMES.

It has a companion, which Harlequin calls REBINDING and Symbolics had a
variant of called ONCE-ONLY which allows you to receive foreign code and
bind it to unique temps either to avoid double-evaluation or to allow you
to substitute into hostile code without accidental capture. e.g.:

 (defmacro twice (x) (rebinding (x) `(* ,x ,x))) ;avoid double-evaluation
 (twice x) == (let ((#1=#:x1 x)) (* #1# #1#))

 (defmacro frob (x y)
   (rebinding (x y)  ;avoid concern about whether X or Y involves the name TEMP
     `(let ((temp (some-computation)))
        (prog1 (frob1 ,x ,y) (cleanup temp)))))
 (frob x y) == (let ((#1=#:x1 x) (#2=#:y1 y))
		 (let ((temp (some-computation)))
		   (prog1 (frob1 #1# #2#) (cleanup temp))))

The Symbolics-variant, called ONCE-ONLY, actually does the substitution
producing (let ((temp (some-computation))) (prog1 (frob x y) (cleanup temp)))
where possible; it requires an &environment arg and a code-walker to do this,
and the key value is that it manages to "win" even when the compiler does not
do aggresive lambda variable substitution.  (The Symbolics compiler can be
made to generate so-so code by excessive use of bound variables, so 
optimizing where possible in macro expansions is needed.) Since the 
Harlequin compiler already aggressively substitutes bound variable values,
cascaded LETs of gensyms are not a problem, and the implementation of service
macros like REBINDING are correspondingly easier.  Heh.  Not that writing
REBINDING is -completely- trivial--it's a fun exercise actually.  I won't
spoil it for you.

In the convolutions of my mind, I think of WITH-UNIQUE-NAMES being to
REBINDING like LAMBDA is to LET; the former in each pair leaves open
the question of what will be bound to its named variable, while the
latter both creates a name and associates it a meaning in one shot.
If you don't see it this way, don't think to hard.  It may hurt your
brain and I wish no responsibility.  But it's obvious that these two
functions have a relationship of some kind and it took me a long time
to figure out how to think about that relationship and particularly
why there had to be two such functions and they couldn't just be
unified somehow.
 --Kent (on vacation, just reading along for the fun of it;
         more evidence that Lisp is fun)