all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: sokobania.01@gmail.com
To: help-gnu-emacs@gnu.org
Subject: Re: How the backquote and the comma really work?
Date: Tue, 30 Jun 2015 09:27:45 -0700 (PDT)	[thread overview]
Message-ID: <00a67642-4ca9-4e01-af0b-0799426132e1@googlegroups.com> (raw)
In-Reply-To: <mailman.5657.1435252169.904.help-gnu-emacs@gnu.org>

Le jeudi 25 juin 2015 19:09:31 UTC+2, Marcin Borkowski a écrit :
> Hi all,
> 
> I decided that the time has come that I finally approach the scary
> backquote-comma duo.  (While I understand it superficially, I'd like to
> get it right and thoroughly this time.)  So my question is whether my
> mental model (see below) is correct.

I made the same decision... long time ago...
Before backquote, I first needed to be clear with "quote" and "eval".
When I fully understood the "'foo" "foo" "(eval 'foo)" "(eval foo)",
I could go for the backquote thing.

I would suggest to read some documentation like:
http://www.gnu.org/software/emacs/manual/html_node/elisp/Backquote.html
http://www.cs.cmu.edu/cgi-bin/info2www?(elisp)Backquote

> So, I assume that when Emacs Lisp interpreter encounters a backquote, it
> looks at the expression after it.  If it is anything but a list, it just
> works like the usual quote, and the backquoted expression evaluates to
> what was backquoted.
> 
> If it is a list, its element are read

as already mentioned, they were read by the reader long time 
before being parsed by the backquote macro itself!

> Michael Heerdegen wrote:
>> Of course, the elements have already been read by the reader.

> and scanned.  If any part of the
> list (probably a nested one) begins with a comma, the whole thing after
> the comma (be it a symbol, a list or whatever) is evaluated as usual,
> and the result is put into the resulting list.

Well... more or less...

The backquote process itself does NOT evaluate anything.
It is better to think of it in terms of expansion.
The evaluation comes AFTER the backquote has expanded its stuff.

When I need to evaluate more than 1 or 2 expressions, i use "M-x ielm"
so that I can see all the results, copy/paste them, etc.

Here, I'll use "print" so that you see both the real thing first
and the way it's pretty-printed in a more human-readable way.

ELISP> (print (read "`',foo"))
(\` (quote (\, foo)))
`',foo

ELISP> (print (macroexpand ''foo))
(quote foo)
'foo

ELISP> (print (macroexpand '`',foo))
(list (quote quote) foo)
(list 'quote foo)

ELISP> (print (macroexpand '`(a ,b c)))
(cons (quote a) (cons b (quote (c))))
(cons 'a
      (cons b
	    '(c)))

In this last example, you can see that `(a ,b c) 
is very close to (list 'a b 'c)
where the function "list" evaluates its arguments:
- 'a evaluates to the symbol "a"
- b evaluates to the symbol-value of the symbol "b"
- 'c evaluates to the symbol "c"
and "list" returns a new list with the these values.

> Whew.  Is that (more or less) right?

Yes! (more or less)

> can I find an Emacs Lisp metacircular evaluator (taking
> into account the quoting mechanisms) anywhere?

You can have a look at https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node367.html

(defun bq-process (x) 
  (cond ((atom x) 
         (list *bq-quote* x)) 
        ((eq (car x) 'backquote) 
         (bq-process (bq-completely-process (cadr x)))) 
        ((eq (car x) *comma*) (cadr x))   ;; <---
        ((eq (car x) *comma-atsign*) 
         (error ",@~S after `" (cadr x))) 
        ((eq (car x) *comma-dot*) 
         (error ",.~S after `" (cadr x))) 
        (t (do ((p x (cdr p)) 
                (q '() (cons (bracket (car p)) q))) 
               ((atom p) 
                (cons *bq-append* 
                      (nreconc q (list (list *bq-quote* p))))) 
             (when (eq (car p) *comma*) 
               (unless (null (cddr p)) (error "Malformed ,~S" p)) 
               (return (cons *bq-append* 
                             (nreconc q (list (cadr p)))))) 
             (when (eq (car p) *comma-atsign*) 
               (error "Dotted ,@~S" p)) 
             (when (eq (car p) *comma-dot*) 
               (error "Dotted ,.~S" p))))))

(remember that ",xx" has already been expanded into "(, xx)",
which is a list with 2 items, the symbol "," and "xx")
On the 6th line, you can see that if "x" is a list beginning with a comma,
the backquote-process just returns whatever is in the 2nd position of this list.

> And I know that I risk starting another thread lasting for dozens of
> messages;-) - but I /do/ want to understand this stuff...  In fact, in
> the spirit of another recent discussion, I want to write a simple code
> analyzer, finding one-legged 'if's and suggesting replacing them with
> 'when's or 'unless'es.

Good idea!

>  This is trivial unless (pun intended) you want
> to take (back)quotes into consideration.

You probably don't want to rewrite a reader!
I would suggest that you "just" write a parser, something like:
(until (eof)
  (parse (read)))

So, you must be very clear with what you'll get from the reader.
Remember the "read" process skips comments and 
"recognizes/creates" a lot of stuff,
like strings, symbols, numbers, lists, etc.

During this process, the macro characters have already been expanded:
"`xx" -> "(`xx)"
but the macro function "`" has NOT been expanded yet.

Maybe your code could force the expansion:
(until (eof)
  (parse (macroexpand (read))))

HTH
)jack(


       reply	other threads:[~2015-06-30 16:27 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <mailman.5657.1435252169.904.help-gnu-emacs@gnu.org>
2015-06-30 16:27 ` sokobania.01 [this message]
2015-06-25 17:09 How the backquote and the comma really work? Marcin Borkowski
2015-06-25 17:33 ` Michael Heerdegen
2015-06-25 18:06   ` Marcin Borkowski
2015-06-25 18:22     ` Michael Heerdegen
2015-06-25 18:39       ` Marcin Borkowski
2015-06-25 18:44         ` Marcin Borkowski
2015-06-25 19:06           ` Michael Heerdegen
2015-07-10 11:36         ` Marcin Borkowski
2015-07-12 15:54           ` Michael Heerdegen
2015-07-12 19:55             ` Marcin Borkowski
2015-07-12 20:33               ` Marcin Borkowski
2015-07-14 18:17                 ` Marcin Borkowski
2015-07-14 22:08                   ` Emanuel Berg
2015-07-21 22:08                   ` Michael Heerdegen
2015-07-24 13:01                     ` Michael Heerdegen
2015-08-11 11:41                       ` Marcin Borkowski
2015-08-12 15:29                         ` Michael Heerdegen
     [not found]                         ` <mailman.8207.1439393377.904.help-gnu-emacs@gnu.org>
2015-08-12 16:30                           ` Pascal J. Bourguignon
2015-08-23  8:30                             ` Marcin Borkowski
     [not found]                             ` <mailman.110.1440318650.11330.help-gnu-emacs@gnu.org>
2015-08-23 16:46                               ` Pascal J. Bourguignon
2015-07-21 21:54                 ` Michael Heerdegen
2015-08-11 10:15                   ` Marcin Borkowski
2015-08-11 17:20                     ` Thorsten Jolitz
2015-08-12 15:01                       ` Michael Heerdegen
2015-07-21 21:50               ` Michael Heerdegen
2015-06-25 18:10 ` Drew Adams
2015-06-25 18:40   ` Michael Heerdegen
2015-06-25 18:53     ` Marcin Borkowski
2015-06-25 19:39       ` Michael Heerdegen
2015-06-25 20:05         ` Drew Adams
2015-06-25 20:18           ` Marcin Borkowski
2015-06-25 20:37             ` Drew Adams
2015-06-25 23:55     ` Robert Thorpe
     [not found]     ` <mailman.5697.1435276533.904.help-gnu-emacs@gnu.org>
2015-06-26  1:41       ` Rusi
2015-06-26 14:24         ` Michael Heerdegen
     [not found]         ` <mailman.5716.1435328741.904.help-gnu-emacs@gnu.org>
2015-06-26 14:35           ` Rusi
2015-06-26 14:51             ` Michael Heerdegen
2015-06-25 18:46   ` Marcin Borkowski
2015-06-26  7:31 ` tomas
2015-06-26 13:48   ` Drew Adams
2015-06-26 14:06     ` tomas
2015-06-26 15:06 ` Emanuel Berg
2015-07-12 17:38 ` Vaidheeswaran C

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=00a67642-4ca9-4e01-af0b-0799426132e1@googlegroups.com \
    --to=sokobania.01@gmail.com \
    --cc=help-gnu-emacs@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.