From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Pascal Bourguignon Newsgroups: gmane.emacs.help Subject: Re: Using setq to obtain a symbol from a list, so that I can assign a function to it Date: Thu, 24 Apr 2008 00:14:04 +0200 Organization: Informatimago Message-ID: <87wsmote1f.fsf@hubble.informatimago.com> References: <48505b79-009c-42c9-912f-219a06474731@f24g2000prh.googlegroups.com> <530940ca-d019-42d4-ba15-c8674a8eb858@59g2000hsb.googlegroups.com> NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: ger.gmane.org 1208990458 27634 80.91.229.12 (23 Apr 2008 22:40:58 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Wed, 23 Apr 2008 22:40:58 +0000 (UTC) To: help-gnu-emacs@gnu.org Original-X-From: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Thu Apr 24 00:41:31 2008 connect(): Connection refused Return-path: Envelope-to: geh-help-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.50) id 1JoneU-0001SL-1C for geh-help-gnu-emacs@m.gmane.org; Thu, 24 Apr 2008 00:41:22 +0200 Original-Received: from localhost ([127.0.0.1]:47110 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Jondo-0003tT-8e for geh-help-gnu-emacs@m.gmane.org; Wed, 23 Apr 2008 18:40:40 -0400 Original-Path: shelby.stanford.edu!newsfeed.stanford.edu!news.tele.dk!news.tele.dk!small.news.tele.dk!feeder1-2.proxad.net!proxad.net!feeder1-1.proxad.net!cleanfeed4-b.proxad.net!nnrp1-2.free.fr!not-for-mail Original-Newsgroups: gnu.emacs.help Face: iVBORw0KGgoAAAANSUhEUgAAADAAAAAwAQMAAABtzGvEAAAABlBMVEUAAAD///+l2Z/dAAAA oElEQVR4nK3OsRHCMAwF0O8YQufUNIQRGIAja9CxSA55AxZgFO4coMgYrEDDQZWPIlNAjwq9 033pbOBPtbXuB6PKNBn5gZkhGa86Z4x2wE67O+06WxGD/HCOGR0deY3f9Ijwwt7rNGNf6Oac l/GuZTF1wFGKiYYHKSFAkjIo1b6sCYS1sVmFhhhahKQssRjRT90ITWUk6vvK3RsPGs+M1RuR mV+hO/VvFAAAAABJRU5ErkJggg== X-Accept-Language: fr, es, en X-Disabled: X-No-Archive: no User-Agent: Gnus/5.1008 (Gnus v5.10.8) Emacs/22.1 (gnu/linux) Cancel-Lock: sha1:FY9iF9mqAekb2x2UUOgTMU4Y24Y= Original-Lines: 307 Original-NNTP-Posting-Date: 24 Apr 2008 00:09:26 MEST Original-NNTP-Posting-Host: 88.180.86.168 Original-X-Trace: 1208988566 news-1.free.fr 26516 88.180.86.168:56384 Original-X-Complaints-To: abuse@proxad.net Original-Xref: shelby.stanford.edu gnu.emacs.help:158138 X-BeenThere: help-gnu-emacs@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Users list for the GNU Emacs text editor List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Errors-To: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.help:53506 Archived-At: srinik001@hotmail.com writes: > Thanks for the tip. Now, it does not throw an error. But I still don't > get what I want. Here is what I did: > > (setq grammar '((sentence ::= subject predicate) > (subject ::= article noun) > (predicate ::= verb))) > --> This of course worked. I could see the individual elements, their > car's and cdr's etc. Also, you shouldn't think it terms of car and cdr here. Don't define your grammar as plain lists like this. Define it as a grammar! (define-grammar simple-english :start-symbol sentence :productions ((sentence ::= subject predicate) (subject ::= article noun) (predicate ::= verb))) (Of course, you could represent such grammar exactly as you did, with a simple list of lists, but it would be better to define grammars as CLOS objects (or rather, CLOS-like objects, using eieio) or just plain structures). (require 'cl) (defstruct grammar start-symbol non-terminals terminals productions (generators (make-hash-table))) (defstruct production lhs rhs generator) (defmacro* define-grammar (name &key (start-symbol nil start-symbol-p) productions) `(progn (defvar ,name) (setf ,name (make-grammar :start-symbol ',(if start-symbol-p start-symbol (first (first productions))) :productions (list ,@(mapcar (lambda (prod-sexp) (destructuring-bind (lhs sep &rest rhs) prod-sexp `(make-production :lhs ',lhs :rhs ',rhs :generator (lambda () (error "not generated yet"))))) productions)))) (compute-terminals-and-non-terminals ,name) ',name)) (defun compute-terminals-and-non-terminals (grammar) (let ((non-terminals (mapcar (function production-lhs) (grammar-productions grammar))) (symbols (mapcan (lambda (prod) (copy-list (production-rhs prod))) (grammar-productions grammar)))) (setf (grammar-non-terminals grammar) non-terminals (grammar-terminals grammar) (remove-duplicates (set-difference symbols non-terminals))) grammar)) (defun grammar-symbol-generator (grammar symbol) (gethash symbol (grammar-generators grammar))) (defun set-grammar-symbol-generator (grammar symbol new-generator) (setf (gethash symbol (grammar-generators grammar)) new-generator)) (defsetf grammar-symbol-generator set-grammar-symbol-generator) (pprint (macroexpand '(define-grammar simple-english :start-symbol sentence :productions ((sentence ::= subject predicate) (subject ::= article noun) (predicate ::= verb))))) --> (progn (defvar simple-english) (setf simple-english (make-grammar :start-symbol 'sentence :productions (list (make-production :lhs 'sentence :rhs '(subject predicate) :generator #1= (lambda () (error "not generated yet"))) (make-production :lhs 'subject :rhs '(article noun) :generator #1#) (make-production :lhs 'predicate :rhs '(verb) :generator #1#)))) (compute-terminals-and-non-terminals simple-english) 'simple-english) (define-grammar simple-english :start-symbol sentence :productions ((sentence ::= subject predicate) (subject ::= article noun) (predicate ::= verb))) --> simple-english (grammar-terminals simple-english) --> (verb noun article) (grammar-non-terminals simple-english) --> (sentence subject predicate) (production-rhs (first (grammar-productions simple-english))) --> (subject predicate) > Then I defined the "leaf" level things: > > (defun article() > (insert "article")) > > (defun noun() > (insert "noun")) > > (defun verb() > (insert "verb")) > > Then I tried this: > > (dolist (x grammar) > (set (car x) (dolist (y (cdr (cdr x))) (funcall y))) > > It threw an error saying that it did not know what subject was. Well perhaps. Whatever. Perhaps you mean something like: (let ((grammar simple-english)) (dolist (terminal (grammar-terminals grammar)) (setf (grammar-symbol-generator grammar terminal) (make-terminal-generator grammar terminal))) (dolist (prod (grammar-productions grammar)) (setf (grammar-symbol-generator grammar (production-lhs prod)) (make-non-terminal-generator grammar (production-rhs prod))))) with: (defun make-terminal-generator (grammar terminal) (byte-compile `(lambda () (insert ,(symbol-name terminal)) (insert " ")))) (defun make-non-terminal-generator (grammar rhs) (byte-compile `(lambda () ,@(mapcar (lambda (item) `(funcall (or (grammar-symbol-generator ',grammar ',item) (error "No generator for %S" ',item)))) rhs)))) If you insist, you can always implement all these abstraction using cons car and cdr (but it might be more efficient, and simplier to use defstruct or eieio defclass). (funcall (grammar-symbol-generator simple-english 'sentence)) inserts: article noun verb > Of > course, the way the grammar was described in the list, it did not know > that. So I tried reversing the grammar, thinking that if it went the > other way, it would understand subject before it came to sentence. So, > I tried this. > > (dolist (x (reverse grammar)) > (set (car x) (dolist (y (cdr (cdr x))) (funcall y)))) > > It still gave the same error! It seems that when it does a set > operation, it forgets it in the next iteration of the loop. Lisp-1 vs. Lisp-2. See my first answer. > I apologize if these are trivial questions, but while being *very* > addictive, Lisp seems unlike anything else that I have done before; > perhaps I need to study Lisp a lot more before giving myself exercises > like these, by studying Pascal's reply more carefully - I need to look > up many of the functions/terms he uses. For example, I don't really > get the difference between the quoted and the unquoted - I know they > are different but can't seem to be able to put my finger on the exact > difference. It's the same difference as in English. Pascal's name is written "Pascal". (I'm writting about M. Blaise Pascal of course). Anyways, the first "Pascal" in the above sentence, you interpret it, by fetching from your memory your representation of M. Blaise Pascal: you evaluate it to the value of Pascal (in that context). The second "Pascal", you don't evaluate it. You take it letter for letter, because I quoted it. It represents itself, the word "Pascal". What would be the translation in lisp of that sentence about Pascal? It's the same in lisp: (let ((var 'var)) (format "The value of the variable %S is %S" 'var var)) --> "The value of the variable var is var" Oops, this example is too much. ;-) Let's try again: (let ((var '42)) (format "The value of the variable %S is %S" 'var var)) --> "The value of the variable var is 42" In the call to format, the argument 'var is evaluated. The special operator quote returns its argument unevaluated. Therefore var is not evaluated and returned as is, var itself. The last argument var is evaluated too. It's a symbol, so lisp tries to find its value. There's a binding of the variable var to the value 42, so the result is 42. format is then called with as argument the string, the symbol var and the fixnum 42. Here how you could translate the sentence about Pascal: (defstruct person name) (defvar pascal (make-person :name 'pascal)) (eql (person-name pascal) 'pascal) --> t The variable pascal is bound to a person whose name is the symbol pascal itself. You should read this tutorial specific to emacs lisp: http://www.gnu.org/software/emacs/emacs-lisp-intro/ and of course, browse alot the online documentation and the sources of emacs lisp function. But what you want to do involves plain lisp programming, so you could also learn more, by studying Common Lisp (or at least parts of Common Lisp that have equivalents or that are similar to emacs lisp). For general programming there is much more material to study Common Lisp than emacs lisp. There are some significant differences between the two lisps, but if you know how to program in Common Lisp, you should be able to program in emacs lisp easily (Common Lisp being a richer programming language, you will learn all the notions you have in emacs lisp). Practical Common Lisp http://www.gigamonkeys.com/book/ Common Lisp: A Gentle Introduction to Symbolic Computation http://www-cgi.cs.cmu.edu/afs/cs.cmu.edu/user/dst/www/LispBook/index.html http://www.cs.cmu.edu/~dst/LispBook/ See also: http://www.cliki.net/Education http://www.cliki.net/Online+Tutorials http://www.cliki.net/Lisp%20books -- __Pascal Bourguignon__ http://www.informatimago.com/ PUBLIC NOTICE AS REQUIRED BY LAW: Any use of this product, in any manner whatsoever, will increase the amount of disorder in the universe. Although no liability is implied herein, the consumer is warned that this process will ultimately lead to the heat death of the universe.