From: rock69
Subject: Nested backquotes, I see the light ...
Date: 
Message-ID: <36a671df-a10e-4483-847d-0fec2f8de518@w24g2000prd.googlegroups.com>
Well, it took me some time, but I really think I finally got the hang
of it. Lots of thanks to all the kind people in the newsgroup by the
way, who helped me out. I can finally look at nested backquotes and
pretty much guess in most cases what's gonna come out. And in the more
complicated cases, with a little analysis I've always been able to
figure it out lately with no real problem.

One final note. Reading Paul Graham's Ansi Common Lisp, I've always
had the impression that it's the outer backquote that gets expanded
first, but The HyperSpec seems to say otherwise. Now, with some
googling I've found the following interesting post from a newbie
lisper on the python group. Any opinions on this?

The post (which you can find at http://mail.python.org/pipermail/python-list/2002-September/165000.html):

--------------------------------------------------------------------

NESTED BACKQUOTE

--------------------------------------------------------------------

The [online-version of the] standard-document states:

http://www.lispworks.com/reference/HyperSpec/Body/02_df.htm

"[...] If the backquote syntax is nested, the innermost backquoted
form
should be expanded first. This means that if several commas occur in
a
row, the leftmost one belongs to the innermost backquote.[...]"

=> "the *innermost* backquoted form *should be* expanded first"

This definition is wrong.

------------------------------------------------------------------------
Testing with implementations:

Allegro:
(setq d 1  c 'd  b 'c  a 'b )
`(,a `(,b ,,c))               ; => (B (EXCL::BQ-LIST B D))
              ;;; which is same as: (B `(,B ,D))

LispWorks:

`(,a `(,b ,,c))               ; => (B (SYSTEM::BQ-LIST B D))
              ;;; which is same as: (B `(,B ,D))


We see in the processing of both implementations:

- The *outermost* backquoted form is expanded first
=> direct contradiction to the specification

- The *innermost* backquoted form is processed *partially* by the
outermost backquote to evaluate the ,,c => ,D.

This confirms: The definition of nested backquote is wrong.

------------------------------------------------------------------------
one could say now:

The specification is correct. The implementors are wrong.

--------------------------------------------------------------------
The 'natural' flow of things will help out.

Naturally (as given by reading in the stream) the outermost backquote
is
expanded first.

The Lisp-Reader cannot preview more than *one* char. Thus it is
impossible to detect the existence of the innermost quote to avoid
evaluation of the outermost backquote.

--------------------------------------------------------------------

(setq d 1  c 'd  b 'c  a 'b )

`(,a `(,b ,,c))               ; => (b `(c ,d))
      |_|__||
|_|________|

the only  , prior to a will be processed from the outermost `
the only  , prior to b will be processed from the innermost `
the left  , prior to c will be processed from the innermost `
the right , prior to c will be processed from the outermost `

--------------------------------------------------------------------
The author meant probably this:

If the backquote syntax is nested, the innermost backquoted form
should
be *served*[not expanded] first [with a comma]. This means that if
several commas occur in a row, the leftmost one belongs to the
innermost
backquote [and so on].

in any case:

http://www.lispworks.com/reference/HyperSpec/Body/02_df.htm

"[...] If the backquote syntax is nested, the innermost backquoted
form
should be expanded first.[...]"

is wrong.

--------------------------------------------------------------------
'Looking around'

i follow an suggested link in the specs:

http://www.lispworks.com/reference/HyperSpec/Body/02_dfa.htm

"[...] Implementors who have no particular reason to make one choice
or
another might wish to refer to IEEE Standard for the Scheme
Programming
Language,[...]"

http://www.cs.indiana.edu/scheme-repository/doc.standards.html

nothing found there,

but i reached finally this point:

http://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-7.html#%_sec_4.2.6
"[...]
Quasiquote forms may be nested. Substitutions are made only for
unquoted
components appearing at the same nesting level as the outermost
backquote. The nesting level increases by one inside each successive
quasiquotation, and decreases by one inside each unquotation.

`(a `(b ,(+ 1 2) ,(foo ,(+ 1 3) d) e) f)
                 ===>  (a `(b ,(+ 1 2) ,(foo 4 d) e) f)
(let ((name1 'x)
       (name2 'y))
   `(a `(b ,,name1 ,',name2 d) e))
                 ===>  (a `(b ,x ,'y d) e)
[...]
"

Which confirms what already is obvious:

The ANSI Common Lisp specification about nested Backquote is wrong.

My main interest now is:

I've lost *many* time due to this wrong specification, which ruins my
understanding process for days.

I've invested *many* time to find out whats happened and to write
everything down, so other newcomers to lisp (i'm a lisp-novice) don't
run into the same problem.

From: John Thingstad
Subject: Re: Nested backquotes, I see the light ...
Date: 
Message-ID: <op.ugyv4507ut4oq5@pandora.alfanett.no>
P� Thu, 04 Sep 2008 18:14:57 +0200, skrev rock69 <···········@gmail.com>:

I won't go into details, but it might be helpful to look at Guy Steele's  
sample implementation of backquote in  "Common Lisp the language 2"  
appendix C backquote
http://www.cs.cmu.edu/afs/cs/project/ai-repository/ai/html/cltl/clm/node367.html#SECTION003600000000000000000

--------------
John Thingstad
From: Rainer Joswig
Subject: Re: Nested backquotes, I see the light ...
Date: 
Message-ID: <joswig-8D8F9A.19372304092008@news-europe.giganews.com>
In article 
<····································@w24g2000prd.googlegroups.com>,
 rock69 <···········@gmail.com> wrote:

> Well, it took me some time, but I really think I finally got the hang
> of it. Lots of thanks to all the kind people in the newsgroup by the
> way, who helped me out. I can finally look at nested backquotes and
> pretty much guess in most cases what's gonna come out. And in the more
> complicated cases, with a little analysis I've always been able to
> figure it out lately with no real problem.
> 
> One final note. Reading Paul Graham's Ansi Common Lisp, I've always
> had the impression that it's the outer backquote that gets expanded
> first, but The HyperSpec seems to say otherwise. Now, with some
> googling I've found the following interesting post from a newbie
> lisper on the python group. Any opinions on this?
> 
> The post (which you can find at http://mail.python.org/pipermail/python-list/2002-September/165000.html):
> 
> --------------------------------------------------------------------
> 
> NESTED BACKQUOTE
> 
> --------------------------------------------------------------------
> 
> The [online-version of the] standard-document states:
> 
> http://www.lispworks.com/reference/HyperSpec/Body/02_df.htm
> 
> "[...] If the backquote syntax is nested, the innermost backquoted
> form
> should be expanded first. This means that if several commas occur in
> a
> row, the leftmost one belongs to the innermost backquote.[...]"
> 
> => "the *innermost* backquoted form *should be* expanded first"
> 
> This definition is wrong.
> 
> ------------------------------------------------------------------------
> Testing with implementations:
> 
> Allegro:
> (setq d 1  c 'd  b 'c  a 'b )
> `(,a `(,b ,,c))               ; => (B (EXCL::BQ-LIST B D))
>               ;;; which is same as: (B `(,B ,D))
> 
> LispWorks:
> 
> `(,a `(,b ,,c))               ; => (B (SYSTEM::BQ-LIST B D))
>               ;;; which is same as: (B `(,B ,D))

You are mixing evaluation and reading.

Try to view it as two stages:

1) READing

CL-USER 26 > (read-from-string "`(,a `(,b ,,c))")
(SYSTEM::BQ-LIST A (SYSTEM::BQ-LIST (QUOTE SYSTEM::BQ-LIST) (QUOTE B) C))
15


2) EVALuation

CL-USER 27 > (eval *)
(B (SYSTEM::BQ-LIST B D))


Reading backquotes is a feature of the reader. The whole form is read and
transformed during the reading stage.

Remember the REPL is

(loop (print (eval (read)))).

First READing, then evaluation. 

> 
> 
> We see in the processing of both implementations:
> 
> - The *outermost* backquoted form is expanded first
> => direct contradiction to the specification
> 
> - The *innermost* backquoted form is processed *partially* by the
> outermost backquote to evaluate the ,,c => ,D.
> 
> This confirms: The definition of nested backquote is wrong.
> 
> ------------------------------------------------------------------------
> one could say now:
> 
> The specification is correct. The implementors are wrong.
> 
> --------------------------------------------------------------------
> The 'natural' flow of things will help out.
> 
> Naturally (as given by reading in the stream) the outermost backquote
> is
> expanded first.
> 
> The Lisp-Reader cannot preview more than *one* char. Thus it is
> impossible to detect the existence of the innermost quote to avoid
> evaluation of the outermost backquote.
> 
> --------------------------------------------------------------------
> 
> (setq d 1  c 'd  b 'c  a 'b )
> 
> `(,a `(,b ,,c))               ; => (b `(c ,d))
>       |_|__||
> |_|________|
> 
> the only  , prior to a will be processed from the outermost `
> the only  , prior to b will be processed from the innermost `
> the left  , prior to c will be processed from the innermost `
> the right , prior to c will be processed from the outermost `
> 
> --------------------------------------------------------------------
> The author meant probably this:
> 
> If the backquote syntax is nested, the innermost backquoted form
> should
> be *served*[not expanded] first [with a comma]. This means that if
> several commas occur in a row, the leftmost one belongs to the
> innermost
> backquote [and so on].
> 
> in any case:
> 
> http://www.lispworks.com/reference/HyperSpec/Body/02_df.htm
> 
> "[...] If the backquote syntax is nested, the innermost backquoted
> form
> should be expanded first.[...]"
> 
> is wrong.
> 
> --------------------------------------------------------------------
> 'Looking around'
> 
> i follow an suggested link in the specs:
> 
> http://www.lispworks.com/reference/HyperSpec/Body/02_dfa.htm
> 
> "[...] Implementors who have no particular reason to make one choice
> or
> another might wish to refer to IEEE Standard for the Scheme
> Programming
> Language,[...]"
> 
> http://www.cs.indiana.edu/scheme-repository/doc.standards.html
> 
> nothing found there,
> 
> but i reached finally this point:
> 
> http://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-7.html#%_sec_4.2.6
> "[...]
> Quasiquote forms may be nested. Substitutions are made only for
> unquoted
> components appearing at the same nesting level as the outermost
> backquote. The nesting level increases by one inside each successive
> quasiquotation, and decreases by one inside each unquotation.
> 
> `(a `(b ,(+ 1 2) ,(foo ,(+ 1 3) d) e) f)
>                  ===>  (a `(b ,(+ 1 2) ,(foo 4 d) e) f)
> (let ((name1 'x)
>        (name2 'y))
>    `(a `(b ,,name1 ,',name2 d) e))
>                  ===>  (a `(b ,x ,'y d) e)
> [...]
> "
> 
> Which confirms what already is obvious:
> 
> The ANSI Common Lisp specification about nested Backquote is wrong.
> 
> My main interest now is:
> 
> I've lost *many* time due to this wrong specification, which ruins my
> understanding process for days.
> 
> I've invested *many* time to find out whats happened and to write
> everything down, so other newcomers to lisp (i'm a lisp-novice) don't
> run into the same problem.

-- 
http://lispm.dyndns.org/
From: Kaz Kylheku
Subject: Re: Nested backquotes, I see the light ...
Date: 
Message-ID: <20080904142527.419@gmail.com>
On 2008-09-04, rock69 <···········@gmail.com> wrote:
> Well, it took me some time, but I really think I finally got the hang
> of it. Lots of thanks to all the kind people in the newsgroup by the
> way, who helped me out. I can finally look at nested backquotes and
> pretty much guess in most cases what's gonna come out. And in the more
> complicated cases, with a little analysis I've always been able to
> figure it out lately with no real problem.
>
> One final note. Reading Paul Graham's Ansi Common Lisp, I've always
> had the impression that it's the outer backquote that gets expanded
> first, but The HyperSpec seems to say otherwise.

Actually, it doesn't matter. The entire backquote is a piece of syntax which
represents list construction. It's processed by some kind of backquote
translator, which converts it into code which performs the required
construction. The expansion order depends on the algorithm used.

Also, it's up to the implementation whether the entire backquote (all of its
nestings) is expanded up front, before any evaluation takes place, or whether
expansion is interleaved into the evaluation rounds.

A nested backquote can be expanded superficially, such that when it is
evaluated, it produces the inner backquote, which is expanded at that time.

Concretely, ``EXPR may actually expand to code which, when evaluated, produces
`EXPR: a backquote which now needs to be expanded again. Or ``EXPR may be fully
expanded; it may produce code which, when evaluated, doesn't produce `EXPR, but
direclty produces the already expanded version of `EXPR.

A ``full backquote expander'' of this type will most likely recurse over the
backquote, and in fact do the expansion bottom-up: it won't synthesize the
outer expansion, until it has done the inside part which it needs as a
constituent.

> Testing with implementations:
>
> Allegro:
> (setq d 1  c 'd  b 'c  a 'b )
> `(,a `(,b ,,c))               ; => (B (EXCL::BQ-LIST B D))
>               ;;; which is same as: (B `(,B ,D))

It's equivalent, but not the same. 

For the purpose of programming with backquotes, the (EXCL::BQ-LIST B D)
(partial) expansion of the inner backquote is not particularly helpful.

The best mental model is that `(,a `(,b ,,c)) produces (B `(,B ,D)) is the best
one.  Implementations which produce results that agree closely with the mental
model are easier for learning about backquotes, and debugging.

> LispWorks:
>
> `(,a `(,b ,,c))               ; => (B (SYSTEM::BQ-LIST B D))
>               ;;; which is same as: (B `(,B ,D))

Now here is CLISP:

  `(,a `(,b ,,c))     =>      (B (LIST B D))

CLISP has an aggressive backquote expander which reduces arbitrary
backquote nesting in one expansion round.

The backquote syntax is turned into a macro, and the macro basically translates
the entire construct to code. Inner backquotes are also turned into the macro,
but the macro walks the structure itself, finds these embedded backquote calls
and expands them.

Here is another:

  `(,a `(,b `(,,,c)))  =>  (B (LIST B (LIST 'LIST D)))

This implementation is not that helpful for learning about backquotes.  It is
efficient. If you write macros which write macros, the second-order macros do
not have to perform any more backquote expansion.

The CLISP implementation has fairly straightforward internals, which can be
easily patched to produce a completely different behavior. The CLISP backquote
macro can be modified so that it doesn't expand the inner backquotes, but
leaves them alone. They will then be expanded when they are evaluated.
The result is completely readable backquote expansion; you in fact get this:

  ;; patched CLISP:

  `(,a `(,b ,,c))   =>   (B `(,B ,D))

The backquote macro is retained in the output, and the pretty printer
recognizes it, rendering it back into the backquote read notation.

The end result, when two evaluations are applied, is the same.

The patch is quite simple.

> - The *outermost* backquoted form is expanded first
>=> direct contradiction to the specification
>
> - The *innermost* backquoted form is processed *partially* by the
> outermost backquote to evaluate the ,,c => ,D.
>
> This confirms: The definition of nested backquote is wrong.

That is not true. The definition describes the semantics in terms of an
unoptimized algorithm. The algorithm pins down the behavior. 

Implementations can use other algorithms, as long as they produce
the same behavior.

> The Lisp-Reader cannot preview more than *one* char. Thus it is
> impossible to detect the existence of the innermost quote to avoid
> evaluation of the outermost backquote.

The Lisp reader can reduce the entire backquote expression into macro
syntax, so that the expansion is left up to the macro.

The macro can traverse its form arbitrarily; it is not constrained to one token
of lookahead.

> in any case:
>
> http://www.lispworks.com/reference/HyperSpec/Body/02_df.htm
>
> "[...] If the backquote syntax is nested, the innermost backquoted
> form
> should be expanded first.[...]"
>
> is wrong.

This is right with respect to the reference algorithm.

It's not right if it is interpreted as a general guideline that all
implementations must obey. But that's an incorrect interpretation.

The reason it's right with respect to the reference algorithm is that
the algorithm's basic recursion kernel doesn't contain cases for recognizing an
inner backquote.  The inner backquotes must be recognized first, otherwise the
algorithm doesn't know what to do with them.

Given

  `(x1 x2 ... xn)

the translation is

  (append [x1] [x2] ... [xn])

where these transformations are applied:

  [form] -> (list `form)
  [,form] -> (list form)
  [,@form] -> form

Nowhere among these cases is it stated what ought to be done if the form
is this:

  [`form] -> ???

The algorithm would choke on this, if it were not for the rule ``inner
backquotes are expanded first''.  Thanks to this rule, the [`form] case goes
away; the backquote expander must recognize [`form], and expand it to produce
some [expanded-form] , which can then be handled through the first case:

  [expanded-form] -> (list `expanded-form)

The outer backquote remains, and jumps down to the expanded backquote; it must
now be subject to further processing: the `expanded-form is still backquoted
and must be expanded now.

> http://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-7.html#%_sec_4.2.6
> "[...]
> Quasiquote forms may be nested. Substitutions are made only for
> unquoted
> components appearing at the same nesting level as the outermost
> backquote. The nesting level increases by one inside each successive
> quasiquotation, and decreases by one inside each unquotation.
>
> `(a `(b ,(+ 1 2) ,(foo ,(+ 1 3) d) e) f)
>                  ===>  (a `(b ,(+ 1 2) ,(foo 4 d) e) f)
> (let ((name1 'x)
>        (name2 'y))
>    `(a `(b ,,name1 ,',name2 d) e))
>                  ===>  (a `(b ,x ,'y d) e)

The problem with this specification is that it seems to rule out optimization.

Common Lisp backquote impelmentations can aggressively reduce an entire
backquote to code, which is not required to regurgitate the inner backquotes as
backquotes.

 ;; CLISP
 
 `(a `(b ,(+ 1 2) ,(foo ,(+ 1 3) d) e) f)

 => 
 
 (A (CONS 'B (CONS '3 (CONS (FOO 4 D) '(E)))) F)


This output is better than the clumsy one required by Scheme, which requires
more backquote processing.  It's a complete reduction the backquote to code.

But, this output is, in many ways, less educational than the Scheme behavior,
from the perspective of someone looking for an interactive tutorial in nested
backquote semantics.

> I've lost *many* time due to this wrong specification, which ruins my
> understanding process for days.

The specification isn't wrong, it's just a poor user guide.  It describes a
good algorithm that's easy to implement, and which decimates the entire
backquote to code. Although its output is inefficient, characterized by naive
forms in the pattern of  (APPEND (LIST ...) ...), it's easy to add
optimization.
From: rock69
Subject: Re: Nested backquotes, I see the light ...
Date: 
Message-ID: <5c5510e5-3ed4-4c99-a706-05520f298f2d@m73g2000hsh.googlegroups.com>
On Sep 5, 12:38 am, Kaz Kylheku <········@gmail.com> wrote:
> On 2008-09-04, rock69 <···········@gmail.com> wrote:
>
> > Well, it took me some time, but I really think I finally got the hang
> > of it. Lots of thanks to all the kind people in the newsgroup by the
> > way, who helped me out. I can finally look at nested backquotes and
> > pretty much guess in most cases what's gonna come out. And in the more
> > complicated cases, with a little analysis I've always been able to
> > figure it out lately with no real problem.
>
> > One final note. Reading Paul Graham's Ansi Common Lisp, I've always
> > had the impression that it's the outer backquote that gets expanded
> > first, but The HyperSpec seems to say otherwise.
>
> Actually, it doesn't matter. The entire backquote is a piece of syntax which
> represents list construction. It's processed by some kind of backquote
> translator, which converts it into code which performs the required
> construction. The expansion order depends on the algorithm used.
>
> Also, it's up to the implementation whether the entire backquote (all of its
> nestings) is expanded up front, before any evaluation takes place, or whether
> expansion is interleaved into the evaluation rounds.
>
> A nested backquote can be expanded superficially, such that when it is
> evaluated, it produces the inner backquote, which is expanded at that time.
>
> Concretely, ``EXPR may actually expand to code which, when evaluated, produces
> `EXPR: a backquote which now needs to be expanded again. Or ``EXPR may be fully
> expanded; it may produce code which, when evaluated, doesn't produce `EXPR, but
> direclty produces the already expanded version of `EXPR.
>
> A ``full backquote expander'' of this type will most likely recurse over the
> backquote, and in fact do the expansion bottom-up: it won't synthesize the
> outer expansion, until it has done the inside part which it needs as a
> constituent.
>
> > Testing with implementations:
>
> > Allegro:
> > (setq d 1  c 'd  b 'c  a 'b )
> > `(,a `(,b ,,c))               ; => (B (EXCL::BQ-LIST B D))
> >               ;;; which is same as: (B `(,B ,D))
>
> It's equivalent, but not the same.
>
> For the purpose of programming with backquotes, the (EXCL::BQ-LIST B D)
> (partial) expansion of the inner backquote is not particularly helpful.
>
> The best mental model is that `(,a `(,b ,,c)) produces (B `(,B ,D)) is the best
> one.  Implementations which produce results that agree closely with the mental
> model are easier for learning about backquotes, and debugging.
>
> > LispWorks:
>
> > `(,a `(,b ,,c))               ; => (B (SYSTEM::BQ-LIST B D))
> >               ;;; which is same as: (B `(,B ,D))
>
> Now here is CLISP:
>
>   `(,a `(,b ,,c))     =>      (B (LIST B D))
>
> CLISP has an aggressive backquote expander which reduces arbitrary
> backquote nesting in one expansion round.
>
> The backquote syntax is turned into a macro, and the macro basically translates
> the entire construct to code. Inner backquotes are also turned into the macro,
> but the macro walks the structure itself, finds these embedded backquote calls
> and expands them.
>
> Here is another:
>
>   `(,a `(,b `(,,,c)))  =>  (B (LIST B (LIST 'LIST D)))
>
> This implementation is not that helpful for learning about backquotes.  It is
> efficient. If you write macros which write macros, the second-order macros do
> not have to perform any more backquote expansion.
>
> The CLISP implementation has fairly straightforward internals, which can be
> easily patched to produce a completely different behavior. The CLISP backquote
> macro can be modified so that it doesn't expand the inner backquotes, but
> leaves them alone. They will then be expanded when they are evaluated.
> The result is completely readable backquote expansion; you in fact get this:
>
>   ;; patched CLISP:
>
>   `(,a `(,b ,,c))   =>   (B `(,B ,D))
>
> The backquote macro is retained in the output, and the pretty printer
> recognizes it, rendering it back into the backquote read notation.
>
> The end result, when two evaluations are applied, is the same.
>
> The patch is quite simple.
>
> > - The *outermost* backquoted form is expanded first
> >=> direct contradiction to the specification
>
> > - The *innermost* backquoted form is processed *partially* by the
> > outermost backquote to evaluate the ,,c => ,D.
>
> > This confirms: The definition of nested backquote is wrong.
>
> That is not true. The definition describes the semantics in terms of an
> unoptimized algorithm. The algorithm pins down the behavior.
>
> Implementations can use other algorithms, as long as they produce
> the same behavior.
>
> > The Lisp-Reader cannot preview more than *one* char. Thus it is
> > impossible to detect the existence of the innermost quote to avoid
> > evaluation of the outermost backquote.
>
> The Lisp reader can reduce the entire backquote expression into macro
> syntax, so that the expansion is left up to the macro.
>
> The macro can traverse its form arbitrarily; it is not constrained to one token
> of lookahead.
>
> > in any case:
>
> >http://www.lispworks.com/reference/HyperSpec/Body/02_df.htm
>
> > "[...] If the backquote syntax is nested, the innermost backquoted
> > form
> > should be expanded first.[...]"
>
> > is wrong.
>
> This is right with respect to the reference algorithm.
>
> It's not right if it is interpreted as a general guideline that all
> implementations must obey. But that's an incorrect interpretation.
>
> The reason it's right with respect to the reference algorithm is that
> the algorithm's basic recursion kernel doesn't contain cases for recognizing an
> inner backquote.  The inner backquotes must be recognized first, otherwise the
> algorithm doesn't know what to do with them.
>
> Given
>
>   `(x1 x2 ... xn)
>
> the translation is
>
>   (append [x1] [x2] ... [xn])
>
> where these transformations are applied:
>
>   [form] -> (list `form)
>   [,form] -> (list form)
>   [,@form] -> form
>
> Nowhere among these cases is it stated what ought to be done if the form
> is this:
>
>   [`form] -> ???
>
> The algorithm would choke on this, if it were not for the rule ``inner
> backquotes are expanded first''.  Thanks to this rule, the [`form] case goes
> away; the backquote expander must recognize [`form], and expand it to produce
> some [expanded-form] , which can then be handled through the first case:
>
>   [expanded-form] -> (list `expanded-form)
>
> The outer backquote remains, and jumps down to the expanded backquote; it must
> now be subject to further processing: the `expanded-form is still backquoted
> and must be expanded now.
>
> >http://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-7.html...
> > "[...]
> > Quasiquote forms may be nested. Substitutions are made only for
> > unquoted
> > components appearing at the same nesting level as the outermost
> > backquote. The nesting level increases by one inside each successive
> > quasiquotation, and decreases by one inside each unquotation.
>
> > `(a `(b ,(+ 1 2) ,(foo ,(+ 1 3) d) e) f)
> >                  ===>  (a `(b ,(+ 1 2) ,(foo 4 d) e) f)
> > (let ((name1 'x)
> >        (name2 'y))
> >    `(a `(b ,,name1 ,',name2 d) e))
> >                  ===>  (a `(b ,x ,'y d) e)
>
> The problem with this specification is that it seems to rule out optimization.
>
> Common Lisp backquote impelmentations can aggressively reduce an entire
> backquote to code, which is not required to regurgitate the inner backquotes as
> backquotes.
>
>  ;; CLISP
>
>  `(a `(b ,(+ 1 2) ,(foo ,(+ 1 3) d) e) f)
>
>  =>
>
>  (A (CONS 'B (CONS '3 (CONS (FOO 4 D) '(E)))) F)
>
> This output is better than the clumsy one required by Scheme, which requires
> more backquote processing.  It's a complete reduction the backquote to code.
>
> But, this output is, in many ways, less educational than the Scheme behavior,
> from the perspective of someone looking for an interactive tutorial in nested
> backquote semantics.
>
> > I've lost *many* time due to this wrong specification, which ruins my
> > understanding process for days.
>
> The specification isn't wrong, it's just a poor user guide.  It describes a
> good algorithm that's easy to implement, and which decimates the entire
> backquote to code. Although its output is inefficient, characterized by naive
> forms in the pattern of  (APPEND (LIST ...) ...), it's easy to add
> optimization.

Thanks a lot Kaz. That was the most thorough and clear explanation
I've ever come across. I really appreciate it.
From: Dan Weinreb
Subject: Re: Nested backquotes, I see the light ...
Date: 
Message-ID: <217f1728-2e63-44e9-a424-d11589c7e4da@z66g2000hsc.googlegroups.com>
On Sep 4, 12:14 pm, rock69 <···········@gmail.com> wrote:
> Well, it took me some time, but I really think I finally got the hang
> of it. Lots of thanks to all the kind people in the newsgroup by the
> way, who helped me out. I can finally look at nested backquotes and
> pretty much guess in most cases what's gonna come out. And in the more
> complicated cases, with a little analysis I've always been able to
> figure it out lately with no real problem.
>
> One final note. Reading Paul Graham's Ansi Common Lisp, I've always
> had the impression that it's the outer backquote that gets expanded
> first, but The HyperSpec seems to say otherwise. Now, with some
> googling I've found the following interesting post from a newbie
> lisper on the python group. Any opinions on this?
>
> The post (which you can find athttp://mail.python.org/pipermail/python-list/2002-September/165000.ht...
>
> --------------------------------------------------------------------
>
> NESTED BACKQUOTE
>
> --------------------------------------------------------------------
>
> The [online-version of the] standard-document states:
>
> http://www.lispworks.com/reference/HyperSpec/Body/02_df.htm
>
> "[...] If the backquote syntax is nested, the innermost backquoted
> form
> should be expanded first. This means that if several commas occur in
> a
> row, the leftmost one belongs to the innermost backquote.[...]"
>
> => "the *innermost* backquoted form *should be* expanded first"
>
> This definition is wrong.
>
> ------------------------------------------------------------------------
> Testing with implementations:
>
> Allegro:
> (setq d 1  c 'd  b 'c  a 'b )
> `(,a `(,b ,,c))               ; => (B (EXCL::BQ-LIST B D))
>               ;;; which is same as: (B `(,B ,D))
>
> LispWorks:
>
> `(,a `(,b ,,c))               ; => (B (SYSTEM::BQ-LIST B D))
>               ;;; which is same as: (B `(,B ,D))
>
> We see in the processing of both implementations:
>
> - The *outermost* backquoted form is expanded first
> => direct contradiction to the specification
>
> - The *innermost* backquoted form is processed *partially* by the
> outermost backquote to evaluate the ,,c => ,D.
>
> This confirms: The definition of nested backquote is wrong.
>
> ------------------------------------------------------------------------
> one could say now:
>
> The specification is correct. The implementors are wrong.
>
> --------------------------------------------------------------------
> The 'natural' flow of things will help out.
>
> Naturally (as given by reading in the stream) the outermost backquote
> is
> expanded first.
>
> The Lisp-Reader cannot preview more than *one* char. Thus it is
> impossible to detect the existence of the innermost quote to avoid
> evaluation of the outermost backquote.
>
> --------------------------------------------------------------------
>
> (setq d 1  c 'd  b 'c  a 'b )
>
> `(,a `(,b ,,c))               ; => (b `(c ,d))
>       |_|__||
> |_|________|
>
> the only  , prior to a will be processed from the outermost `
> the only  , prior to b will be processed from the innermost `
> the left  , prior to c will be processed from the innermost `
> the right , prior to c will be processed from the outermost `
>
> --------------------------------------------------------------------
> The author meant probably this:
>
> If the backquote syntax is nested, the innermost backquoted form
> should
> be *served*[not expanded] first [with a comma]. This means that if
> several commas occur in a row, the leftmost one belongs to the
> innermost
> backquote [and so on].
>
> in any case:
>
> http://www.lispworks.com/reference/HyperSpec/Body/02_df.htm
>
> "[...] If the backquote syntax is nested, the innermost backquoted
> form
> should be expanded first.[...]"
>
> is wrong.
>
> --------------------------------------------------------------------
> 'Looking around'
>
> i follow an suggested link in the specs:
>
> http://www.lispworks.com/reference/HyperSpec/Body/02_dfa.htm
>
> "[...] Implementors who have no particular reason to make one choice
> or
> another might wish to refer to IEEE Standard for the Scheme
> Programming
> Language,[...]"
>
> http://www.cs.indiana.edu/scheme-repository/doc.standards.html
>
> nothing found there,
>
> but i reached finally this point:
>
> http://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-7.html...
> "[...]
> Quasiquote forms may be nested. Substitutions are made only for
> unquoted
> components appearing at the same nesting level as the outermost
> backquote. The nesting level increases by one inside each successive
> quasiquotation, and decreases by one inside each unquotation.
>
> `(a `(b ,(+ 1 2) ,(foo ,(+ 1 3) d) e) f)
>                  ===>  (a `(b ,(+ 1 2) ,(foo 4 d) e) f)
> (let ((name1 'x)
>        (name2 'y))
>    `(a `(b ,,name1 ,',name2 d) e))
>                  ===>  (a `(b ,x ,'y d) e)
> [...]
> "
>
> Which confirms what already is obvious:
>
> The ANSI Common Lisp specification about nested Backquote is wrong.
>
> My main interest now is:
>
> I've lost *many* time due to this wrong specification, which ruins my
> understanding process for days.
>
> I've invested *many* time to find out whats happened and to write
> everything down, so other newcomers to lisp (i'm a lisp-novice) don't
> run into the same problem.

I don't know what you mean by "which is expanded first".

Are you saying that there are two possible meanings of backquote,
in which the form:

`(,a `(,b ,,c))

could expand in two different ways?  What are the two ways?