From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: sokobania.01@gmail.com Newsgroups: gmane.emacs.help Subject: Re: How the backquote and the comma really work? Date: Tue, 30 Jun 2015 09:27:45 -0700 (PDT) Message-ID: <00a67642-4ca9-4e01-af0b-0799426132e1@googlegroups.com> References: NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable X-Trace: ger.gmane.org 1435681843 6191 80.91.229.3 (30 Jun 2015 16:30:43 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Tue, 30 Jun 2015 16:30:43 +0000 (UTC) To: help-gnu-emacs@gnu.org Original-X-From: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Tue Jun 30 18:30:42 2015 Return-path: Envelope-to: geh-help-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1Z9yQk-0006fj-0A for geh-help-gnu-emacs@m.gmane.org; Tue, 30 Jun 2015 18:30:42 +0200 Original-Received: from localhost ([::1]:47819 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Z9yQj-0002qg-9n for geh-help-gnu-emacs@m.gmane.org; Tue, 30 Jun 2015 12:30:41 -0400 X-Received: by 10.66.141.11 with SMTP id rk11mr28588412pab.26.1435681665326; Tue, 30 Jun 2015 09:27:45 -0700 (PDT) X-Received: by 10.140.23.50 with SMTP id 47mr258817qgo.24.1435681665141; Tue, 30 Jun 2015 09:27:45 -0700 (PDT) Original-Path: usenet.stanford.edu!j8no44445igd.0!news-out.google.com!a16ni9346ign.0!nntp.google.com!j8no44442igd.0!postnews.google.com!glegroupsg2000goo.googlegroups.com!not-for-mail Original-Newsgroups: gnu.emacs.help In-Reply-To: Complaints-To: groups-abuse@google.com Injection-Info: glegroupsg2000goo.googlegroups.com; posting-host=83.145.69.50; posting-account=6AmU8QoAAABkSb2sbJisGlnlR_egh2hP Original-NNTP-Posting-Host: 83.145.69.50 User-Agent: G2/1.0 Injection-Date: Tue, 30 Jun 2015 16:27:45 +0000 Original-Xref: usenet.stanford.edu gnu.emacs.help:213042 X-BeenThere: help-gnu-emacs@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Users list for the GNU Emacs text editor List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Original-Sender: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.help:105330 Archived-At: Le jeudi 25 juin 2015 19:09:31 UTC+2, Marcin Borkowski a =E9crit : > Hi all, >=20 > 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. >=20 > If it is a list, its element are read as already mentioned, they were read by the reader long time=20 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)=20 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/node3= 67.html (defun bq-process (x)=20 (cond ((atom x)=20 (list *bq-quote* x))=20 ((eq (car x) 'backquote)=20 (bq-process (bq-completely-process (cadr x))))=20 ((eq (car x) *comma*) (cadr x)) ;; <--- ((eq (car x) *comma-atsign*)=20 (error ",@~S after `" (cadr x)))=20 ((eq (car x) *comma-dot*)=20 (error ",.~S after `" (cadr x)))=20 (t (do ((p x (cdr p))=20 (q '() (cons (bracket (car p)) q)))=20 ((atom p)=20 (cons *bq-append*=20 (nreconc q (list (list *bq-quote* p)))))=20 (when (eq (car p) *comma*)=20 (unless (null (cddr p)) (error "Malformed ,~S" p))=20 (return (cons *bq-append*=20 (nreconc q (list (cadr p))))))=20 (when (eq (car p) *comma-atsign*)=20 (error "Dotted ,@~S" p))=20 (when (eq (car p) *comma-dot*)=20 (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=20 "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(