Rocksolid Light

News from da outaworlds

mail  files  register  groups  login

Message-ID:  

I think we are in Rats' Alley where the dead men lost their bones. -- T.S. Eliot


comp / comp.lang.lisp / Re: Winstond and Horn Macros

SubjectAuthor
o Re: Winstond and Horn MacrosB. Pym

1
Subject: Re: Winstond and Horn Macros
From: B. Pym
Newsgroups: comp.lang.lisp
Organization: A noiseless patient Spider
Date: Thu, 4 Jul 2024 18:32 UTC
Path: eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: No_spamming@noWhere_7073.org (B. Pym)
Newsgroups: comp.lang.lisp
Subject: Re: Winstond and Horn Macros
Date: Thu, 4 Jul 2024 18:32:11 -0000 (UTC)
Organization: A noiseless patient Spider
Lines: 92
Message-ID: <v66pr6$2scq6$1@dont-email.me>
MIME-Version: 1.0
Content-Type: text/plain; charset=iso-8859-1
Injection-Date: Thu, 04 Jul 2024 20:32:12 +0200 (CEST)
Injection-Info: dont-email.me; posting-host="64c77bec4f9fee50db24fcbb65b4503b";
logging-data="3027782"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/sNgnel6clf7Fiu7dfHmwX"
User-Agent: XanaNews/1.18.1.6
Cancel-Lock: sha1:+pmMQBXIfEaVPnW8aiUbuBFPz00=
View all headers

> Doug Tolton wrote:
> > Problem 12-4 is:
> > Suppose, for some immensely peculiar reason, you want a form of LET
> > that does not evaluate initial value forms. Define LETQ such that
> > LETQ arranges the following translation:
> > (letq ((<variable1> <value1>)
> > (<variable2> <value2>)
> > ...)
> > <body> )
> >
> > translate to:
> >
> > (let ((<variable1> '<value1>)
> > (<variable2> '<value2>)
> > ...)
> > <body> )
>
> [ snip ]
>
> > I
> > could just be missing something simple, but I don't understand how I
> > would take an arbitrary number of variables, and map only value
> > expressions so they aren't evaluated. Is there something simple I'm
> > missing? Or is there an entire conceptual idea I'm not getting?
>
> A macro is just a Lisp function that turns the list (LETQ ...) to (LET
> ...) according to the above schema. Write a function that does this,
> and then turn it into a macro.
>
> You might be confused by the DEFMACRO utility, which has built-in
> destructuring. Prior to things like DEFMACRO, Lisp macros were written
> as ordinary functions that worked on the entire form. A LETQ macro
> would receive just one argument: the entire source code of the macro
> call: (LETQ ...)
>
> With DEFMACRO, you have some built-in analysis. The form is matched
> against a syntactic pattern, and pieces are assigned to variables.
> (You can still receive the entire form in one piece using the &whole
> lambda keyword).
>
> With the preprocessing that DEFMACRO performs, it's no longer as
> obvious to newbies that the macro is a function that turns one form
> into another.
>
> When there are repeated units to be handled, like ((<variable> <value>
> ...)) lists, newbies get confused, because they can't find the right
> DEFMACRO syntax which would nicely destructure it without any
> expenditure of programming work. ;)
>
> The answer is that where DEFMACRO's destructuring runs out of steam,
> you have to switch to ``manual'' list processing. For example, you can
> capture the entire ((<variable> <value>) ...) sublist, attaching it to
> one variable:
>
> (defmacro letq ((&rest variable-value-list) &body forms)
> `(let ,(transform-variable-value-list variable-value-list)
> ,@forms))
>
> Now you just need to write the function TRANSFORM-VARIABLE-VALUE-LIST.
> This can be done using
>
> (loop for (variable value) in variable-value-list
> collecting `(,variable (quote ,value)))
>
> so the whole macro becomes:
>
> (defmacro letq ((&rest variable-value-list) &body forms)
> (let ((transformed-list (loop for (variable value)
> in variable-value-list
> collecting `(,variable ',value))))
> `(let ,transformed-list ,@forms)))
>
> In other words, the function is nice and short so we roll it into the
> body of the macro, thus sparing ourselves a lesson about eval-when. ;)

Let's check the output under SBCL:

* (letq ((a aa) (b bb)) (list a b))
===>
(AA BB)

Scheme

(define-syntax letq
(syntax-rules ()
[(_ ((v s) ...) expr ...)
(let ((v 's) ...) expr ...)]))

(letq ((a aaa) (b bbb) (c ccc)) (list a b c))
===>
(aaa bbb ccc)

1

rocksolid light 0.9.8
clearnet tor