Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Top-level definition of unquote

33 views
Skip to first unread message

Stefan Monnier

unread,
Nov 17, 2021, 9:27:50 PM11/17/21
to

I've been toying with the idea of defining (in ELisp) `,` as a macro
which would "naturally" generalize the `,` of the backquote macro to its
meaning outside of backquotes:

(defmacro \, (exp)
(eval exp))

Then you have that

,`EXP

is equivalent to

EXP

at top-level as well.

AFAICT this is not done in Common-Lisp, so I'm wondering if there's
a particular reason why it is so, and whether other Lisps have adopted
such a thing (or not and why not),


Stefan

Alan Bawden

unread,
Nov 17, 2021, 11:10:06 PM11/17/21
to
Random unconnected thoughts:

Your simple defmacro above will be evaluating that expression in an
environment other than the lexical one where the expression appeared.

Common Lisp has "#." which calls eval at read time.

Lisp Machine Lisp had "#," which was like "#." but delayed executing the
form until load time. "#," was removed from Common Lisp because it was
difficult for everyone to agree on what that meant exactly.

Scheme allows you to write ",foo" anywhere and just reads it as
"(unquote foo)".

Some dialects of Lisp use a leading "," in the read-eval-print loop to
be an escape to some form of command language.

I always thought that it was an advantage in Common Lisp that ","
outside of a backquote was an error, because it would catch mistakes
where I missed a backquote somewhere -- similar to checking that my
parentheses were balanced.

--
Alan Bawden

Kaz Kylheku

unread,
Nov 18, 2021, 3:06:09 AM11/18/21
to
On 2021-11-18, Alan Bawden <al...@csail.mit.edu> wrote:
> Lisp Machine Lisp had "#," which was like "#." but delayed executing the
> form until load time. "#," was removed from Common Lisp because it was
> difficult for everyone to agree on what that meant exactly.

What does that do that isn't covered by load-time-value?

I suppose interpolation into a context that isn't evaluated,
like hash-dot:

(quote (1 2 3 4 #,(+ 2 3))))

But that means that the entire quote does not make sense as a true
literal. It is hard to see what that should mean, and by what
mechanism.

What that code seems to want is for the whole thing to be a load-time
literal:

(load-time-value `(1 2 3 4 ,(+ 2 3)))

The (+ 2 3) happens at load time, gets inserted into a list, and
that list then behaves like a literal in the loaded code.

--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal

Alan Bawden

unread,
Nov 18, 2021, 9:37:01 AM11/18/21
to
Kaz Kylheku <480-99...@kylheku.com> writes:

On 2021-11-18, Alan Bawden <al...@csail.mit.edu> wrote:
> Lisp Machine Lisp had "#," which was like "#." but delayed executing the
> form until load time. "#," was removed from Common Lisp because it was
> difficult for everyone to agree on what that meant exactly.

What does that do that isn't covered by load-time-value?

See below.

I suppose interpolation into a context that isn't evaluated,
like hash-dot:

(quote (1 2 3 4 #,(+ 2 3))))

I believe "#," was in fact restricted to appear only in constants.

But that means that the entire quote does not make sense as a true
literal. It is hard to see what that should mean, and by what
mechanism.

As I recall, it required some support from the way constants were
represented in compiled files.

As I said, "it was difficult for everyone to agree on what that meant
exactly". I believe LOAD-TIME-VALUE was added as a replacement
precisely because people _could_ agree on what it meant.

--
Alan Bawden

Stefan Monnier

unread,
Nov 18, 2021, 3:31:35 PM11/18/21
to
Alan Bawden [2021-11-17 23:09:59] wrote:
> Stefan Monnier <mon...@iro.umontreal.ca> writes:
>
> I've been toying with the idea of defining (in ELisp) `,` as a macro
> which would "naturally" generalize the `,` of the backquote macro to its
> meaning outside of backquotes:
>
> (defmacro \, (exp)
> (eval exp))
>
> Then you have that
>
> ,`EXP
>
> is equivalent to
>
> EXP
>
> at top-level as well.
>
> AFAICT this is not done in Common-Lisp, so I'm wondering if there's
> a particular reason why it is so, and whether other Lisps have adopted
> such a thing (or not and why not),
>
> Random unconnected thoughts:
>
> Your simple defmacro above will be evaluating that expression in an
> environment other than the lexical one where the expression appeared.

Depends what you mean by "the lexical one where the expression appeared".
E.g. in:

`(let ((x 2)) ,(+ x 5))

do you consider the `(x 2)` binding as part of the lexical environment
where `(+ x 5)` appears? [ I hope not. ]

> Common Lisp has "#." which calls eval at read time.
>
> Lisp Machine Lisp had "#," which was like "#." but delayed executing the
> form until load time. "#," was removed from Common Lisp because it was
> difficult for everyone to agree on what that meant exactly.

Hmm... these are quite different: the purpose of the above `,` is to be
able to build *code* at compile-time.

> Scheme allows you to write ",foo" anywhere and just reads it as
> "(unquote foo)".

Same in ELisp: if you write ,foo it'll be read as (\, foo).
The question is whether `unquote` or `,` is globally defined as
a function macro or not.

> I always thought that it was an advantage in Common Lisp that ","
> outside of a backquote was an error, because it would catch mistakes
> where I missed a backquote somewhere -- similar to checking that my
> parentheses were balanced.

Of course, that's the usual tradeoff.

BTW, one downside of the above `,` macro is that it will inevitably make
programmers want to have a matching `,@` top-level functionality, but
that can't be defined as cleanly/simply with a macro.


Stefan

Alan Bawden

unread,
Nov 19, 2021, 1:25:53 AM11/19/21
to
Stefan Monnier <mon...@iro.umontreal.ca> writes:

Alan Bawden [2021-11-17 23:09:59] wrote:
> Random unconnected thoughts:
>
> Your simple defmacro above will be evaluating that expression in an
> environment other than the lexical one where the expression appeared.

Depends what you mean by "the lexical one where the expression appeared".
E.g. in:

`(let ((x 2)) ,(+ x 5))

do you consider the `(x 2)` binding as part of the lexical environment
where `(+ x 5)` appears? [ I hope not. ]

In your example, The lexical environment where "(+ x 5)" appears is, of
course, the environment that surrounds the backquote expression -- which
presumably has a binding for "x". The "x" in "((x 2))" is just a
symbol.

But you are proposing that a naked ",(+ x 5)" will be evaluated in an
environment that does _not_ lexically surround the site where it
occurred. It's an environment that will be _gone_ before any
environment that can be said to surround the comma expression even comes
into existance, because you'll be calling EVAL at macro-expand-time
(which is usually compile-time), and _that_ environment will be dead and
gone before the resulting code is run. That "x", if it refers to
anything at all, refers to a binding that is in no way lexically
apparent at the site of the comma expression.

At least that's the way I understand the word "lexical". That's the way
I was using it when I wrote "the lexical [environment] where the
expression appeared".

> Common Lisp has "#." which calls eval at read time.
>
> Lisp Machine Lisp had "#," which was like "#." but delayed executing the
> form until load time. "#," was removed from Common Lisp because it was
> difficult for everyone to agree on what that meant exactly.

Hmm... these are quite different: the purpose of the above `,` is to be
able to build *code* at compile-time.

They seem pretty similar to me, actually. I can use "#." to build code
as well as data. Read-time and compile-time are pretty close to each
other in practice.

--
Alan Bawden

Stefan Monnier

unread,
Nov 19, 2021, 1:54:05 PM11/19/21
to
> But you are proposing that a naked ",(+ x 5)" will be evaluated in an
> environment that does _not_ lexically surround the site where it
> occurred.

ELisp's definition of which environment is used in such circumstances is
indeed problematic/nonexisting, but if I were to adapt this to something
like the Common Lisp spec, it would make sense to define it as running
in the same surrounding lexical environment as the surrounding lexical
environment that would apply for the body of a `defmacro` or an
`eval-when`, and you'd probably restrict it to be used at top-level.

All the current uses of this kind of `,` macro in ELisp are at top-level.

Basically,

,EXP

is used as a shorthand for

(defmacro XX () EXP)
(XX)

> > Common Lisp has "#." which calls eval at read time.
> >
> > Lisp Machine Lisp had "#," which was like "#." but delayed executing the
> > form until load time. "#," was removed from Common Lisp because it was
> > difficult for everyone to agree on what that meant exactly.
>
> Hmm... these are quite different: the purpose of the above `,` is to be
> able to build *code* at compile-time.
>
> They seem pretty similar to me, actually. I can use "#." to build code
> as well as data. Read-time and compile-time are pretty close to each
> other in practice.

Oh, indeed, thanks.


Stefan
0 new messages