unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
* Using setq to obtain a symbol from a list, so that I can assign a  function to it
@ 2008-04-22  2:28 srinik001
  2008-04-22  5:19 ` srinik001
                   ` (2 more replies)
  0 siblings, 3 replies; 16+ messages in thread
From: srinik001 @ 2008-04-22  2:28 UTC (permalink / raw)
  To: help-gnu-emacs

Hello,

I would really appreciate some help on this. I am trying to do just
about everything with Emacs (and Emacs Lisp) these days. One of the
things I need to do in my job is to create XML files. I thought I
would use Emacs rather than some other editor/tool.

So, I am trying to write a tool that will enable me to write specific
XML files by prompting me to enter values. Here is how I am trying to
do it.

First, I set a variable that will provide a "grammar" for my file that
Emacs will help me write. An example is the following : of course, my
actual problem is not about generating English sentences; this is just
for illustration.

(setq grammar '((sentence <- subject predicate)
		(subject <- article noun)
		(predicate <- verb)))

I expect to generate functions that look like this:

(defun sentence()
  (........some stuff .........)
  (subject)
  (predicate)
  (........some stuff again...))

What I want the system to do is to generate the function
automatically. So, I should have functions for sentence, subject and
predicate. I will of course hand-code the functions for article, noun
and verb.

I don't want to write the above defun; I want to generate it by using
(setq sentence #'(lambda() ( (subject) (predicate)))). Of course,
instead of "sentence". I want to use (car x) or something like that by
reading the variable "grammar".

Here is the problem: when I do this:

(setq (car (expression that generates sentence) #'(lambda() (print
"hello")))

I get an error.

But if I do a (setq x (car ... ) to get the sentence symbol and THEN
assign it, everything works.

Is there something fundamental I am missing?

Thanks,

Regards,

SK




^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Using setq to obtain a symbol from a list, so that I can assign a function to it
  2008-04-22  2:28 Using setq to obtain a symbol from a list, so that I can assign a function to it srinik001
@ 2008-04-22  5:19 ` srinik001
  2008-04-22 12:54   ` Barry Margolin
                     ` (2 more replies)
  2008-04-22 15:22 ` Ted Zlatanov
  2008-04-22 19:59 ` Pascal Bourguignon
  2 siblings, 3 replies; 16+ messages in thread
From: srinik001 @ 2008-04-22  5:19 UTC (permalink / raw)
  To: help-gnu-emacs

Oops... I got the subject wrong. Instead of

" Using setq to obtain a symbol from a list, so that I can assign a
function to it", it should read, "Using setq to assign value to the
result of a function". Sorry about that.

Regards,

SK


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Using setq to obtain a symbol from a list, so that I can assign a function to it
  2008-04-22  5:19 ` srinik001
@ 2008-04-22 12:54   ` Barry Margolin
  2008-04-23  4:40     ` srinik001
  2008-04-23  5:10   ` Kevin Rodgers
       [not found]   ` <mailman.10729.1208927476.18990.help-gnu-emacs@gnu.org>
  2 siblings, 1 reply; 16+ messages in thread
From: Barry Margolin @ 2008-04-22 12:54 UTC (permalink / raw)
  To: help-gnu-emacs

In article 
<a4bb6deb-6337-43bd-95e4-64a29770c803@y18g2000pre.googlegroups.com>,
 srinik001@hotmail.com wrote:

> Oops... I got the subject wrong. Instead of
> 
> " Using setq to obtain a symbol from a list, so that I can assign a
> function to it", it should read, "Using setq to assign value to the
> result of a function". Sorry about that.

Use set instead of setq.

-- 
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Using setq to obtain a symbol from a list, so that I can assign a  function to it
  2008-04-22  2:28 Using setq to obtain a symbol from a list, so that I can assign a function to it srinik001
  2008-04-22  5:19 ` srinik001
@ 2008-04-22 15:22 ` Ted Zlatanov
  2008-04-22 18:36   ` Pascal Bourguignon
  2008-04-22 19:59 ` Pascal Bourguignon
  2 siblings, 1 reply; 16+ messages in thread
From: Ted Zlatanov @ 2008-04-22 15:22 UTC (permalink / raw)
  To: help-gnu-emacs

On Mon, 21 Apr 2008 19:28:03 -0700 (PDT) srinik001@hotmail.com wrote: 

s> So, I am trying to write a tool that will enable me to write specific
s> XML files by prompting me to enter values. Here is how I am trying to
s> do it.

You may want to look at the various templating packages available, in
case one of them does what you want.  Check out skeleton.el in
particular (http://www.emacswiki.org/cgi-bin/wiki/SkeletonMode for some
examples) since any element of the template can itself be a template.
That will probably save you a lot of time.

Anytime you find yourself auto-generating functions you should wonder if
your data structure could be better (sometimes the answer is 'no' :)

Ted


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Using setq to obtain a symbol from a list, so that I can assign a  function to it
  2008-04-22 15:22 ` Ted Zlatanov
@ 2008-04-22 18:36   ` Pascal Bourguignon
  2008-05-17 22:20     ` David Combs
  0 siblings, 1 reply; 16+ messages in thread
From: Pascal Bourguignon @ 2008-04-22 18:36 UTC (permalink / raw)
  To: help-gnu-emacs

Ted Zlatanov <tzz@lifelogs.com> writes:

> On Mon, 21 Apr 2008 19:28:03 -0700 (PDT) srinik001@hotmail.com wrote: 
>
> s> So, I am trying to write a tool that will enable me to write specific
> s> XML files by prompting me to enter values. Here is how I am trying to
> s> do it.
>
> You may want to look at the various templating packages available, in
> case one of them does what you want.  Check out skeleton.el in
> particular (http://www.emacswiki.org/cgi-bin/wiki/SkeletonMode for some
> examples) since any element of the template can itself be a template.
> That will probably save you a lot of time.
>
> Anytime you find yourself auto-generating functions you should wonder if
> your data structure could be better (sometimes the answer is 'no' :)

Well, I wouldn't be so categoric.  You could start by writting an
"interpreter" of your data, but generating lisp is like implementing
the "compiler", so I don't see much difference.  It's so easy to do it
in lisp, that you can go directly to the "compiler".

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

THIS IS A 100% MATTER PRODUCT: In the unlikely event that this
merchandise should contact antimatter in any form, a catastrophic
explosion will result.


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Using setq to obtain a symbol from a list, so that I can assign a  function to it
  2008-04-22  2:28 Using setq to obtain a symbol from a list, so that I can assign a function to it srinik001
  2008-04-22  5:19 ` srinik001
  2008-04-22 15:22 ` Ted Zlatanov
@ 2008-04-22 19:59 ` Pascal Bourguignon
  2008-04-23  3:11   ` Timothy Hobbs
       [not found]   ` <mailman.10727.1208920326.18990.help-gnu-emacs@gnu.org>
  2 siblings, 2 replies; 16+ messages in thread
From: Pascal Bourguignon @ 2008-04-22 19:59 UTC (permalink / raw)
  To: help-gnu-emacs

srinik001@hotmail.com writes:

> Hello,
>
> I would really appreciate some help on this. I am trying to do just
> about everything with Emacs (and Emacs Lisp) these days. One of the
> things I need to do in my job is to create XML files. I thought I
> would use Emacs rather than some other editor/tool.
>
> So, I am trying to write a tool that will enable me to write specific
> XML files by prompting me to enter values. Here is how I am trying to
> do it.
>
> First, I set a variable that will provide a "grammar" for my file that
> Emacs will help me write. An example is the following : of course, my
> actual problem is not about generating English sentences; this is just
> for illustration.
>
> (setq grammar '((sentence  <- subject predicate)
>                 (subject   <- article noun)
>                 (predicate <- verb)))
>
> I expect to generate functions that look like this:
>
> (defun sentence()
>   (........some stuff .........)
>   (subject)
>   (predicate)
>   (........some stuff again...))
>
> What I want the system to do is to generate the function
> automatically. So, I should have functions for sentence, subject and
> predicate. I will of course hand-code the functions for article, noun
> and verb.
>
> I don't want to write the above defun; I want to generate it by using
> (setq sentence #'(lambda() ( (subject) (predicate)))). Of course,
> instead of "sentence". I want to use (car x) or something like that by
> reading the variable "grammar".
>
> Here is the problem: when I do this:
>
> (setq (car (expression that generates sentence) #'(lambda() (print
> "hello")))
>
> I get an error.
>
> But if I do a (setq x (car ... ) to get the sentence symbol and THEN
> assign it, everything works.
>
> Is there something fundamental I am missing?

You're near.

First, remember that emacs lisp is a lisp-2.  That means that a symbol
can have both a function and a value.

defun  sets the function of the symbol.
defvar (setf and setq) set the value of the symbol.

(This is in opposition to scheme which is a lisp-1 and where you only
need to assign a procedure value to a variable to define a function).


So what do you want to generate?
(defun sentence ...) or (setq  sentence (lambda ....)) ?


Also, something you might consider is that there is no package in
emacs lisp, so whether you use the function slot or the value slot of
these symbol, it is global.  Imagine you want to edit an XML
describing some graphic with lines and arrows at the beginning or the
end of the lines.  You could have have this kind of grammar:

(define-grammar graphic-xml
  (graphic           -> lines) 
  (lines             -> )
  (lines             -> line lines)
  (line              -> beginning-of-line line-attributes end-of-lines)
  (beginning-of-line -> x y decoration)
  (end-of-line       -> x y decoration))

Oops! You just redefined the emacs lisp functions beginning-of-line
and end-of-line, and about 30% of the keypresses will now break...

One solution would be to build composed symbol names.  For example,
the global functions and variables defined by ERC, the Emacs iRc
Client all start with erc-.  Another solution is to keep your
generated functions in a hash-table indexed by the symbols.  In this
case, the hash-table defines in a way another namespace. 




Ok, so now let's address your main question.  What you have is
a list containing a grammar production like: 

         ( <name>   ->   <item1> ... <itemN> )

and you want to get a _list_ like:

         (defun <name> ()
             (<item1>)
             ...
             (<itemN>))

Well, there's really no difficulty.  I'm sure you could easily do it.
if defun gives you difficulties, try to generate this list instead:

         (donald <name> mickey  (<item1>) ... (<itemN>))





Here it is:

    (defun generate-production (prod)
       (destructuring-bind (name separator &rest items) prod
          (list* 'defun name '()
                 (mapcar (lambda (item) (list item)) items))))


    (generate-production '(sentence  <- subject predicate))
    --> (defun sentence nil (subject) (predicate))



On the other hand, if you want to put these function into a
hash-table, you could write:

    (defun generate-rhs (items)
       (list* 'lambda '()
               (mapcar (lambda (item) (list item)) items)))

    (defun store-production (grammar production)
       (destructuring-bind (name separator &rest items) production
          (setf (gethash name grammar) (byte-compile (generate-rhs items)))))

    (setq grammar (make-hash-table))
    (store-production grammar '(sentence <- subject predicate))


We can call the function associated with sentence with:

    (funcall (gethash 'sentence grammar))

Note that we don't generate a setf, we just generate the (lambda ...)
compile it, and put the resulting compiled function into the
hash-table.

As for:
> (setq (car (expression that generates sentence) #'(lambda() (print
> "hello")))
yes, you can use set in this situation:

  (destructuring-bind (name separator &rest items) production
     (set name (byte-compile `(lambda () ,@(mapcar 'list items)))))

or, equivalently setf symbol-value:

  (destructuring-bind (name separator &rest items) production
     (setf (symbol-value name) (byte-compile `(lambda () ,@(mapcar 'list items)))))

but it's probably better to but these function in a hash-table than in
the value slots of the symbols.



Instead of writting deep expressions such as:

   (list 'lambda '() 
         (append '(save-excursion)
                  (list (list 'insert '"<" (string name) '">"))
                  forms
                  (list (list 'insert '"</" (string name) '">"))))

you can use backquote and comma to write it more easily:

   `(lambda () 
       (save-excursion
          (insert "<"  ,(string name) ">")
          ,@forms
          (insert "</" ,(string name) ">")))


so for example, you could write:

    (defun make-name (name)
      (intern (format "xml-insert/%s" name)))

    (defun generate-production (prod)
       (destructuring-bind (name separator &rest items) prod
          `(defun ,(make-name name) ()
              (insert ,(format "<%s>" name))
              ,@(mapcar (lambda (item) `(,(make-name item))) items)
              (insert ,(format "</%s>" name)))))

(generate-production '(sentence  <- subject predicate))
--> (defun xml-insert/sentence nil
       (insert "<sentence>")
       (xml-insert/subject)
       (xml-insert/predicate)
       (insert "</sentence>"))





Finally, emacs is not modal.  It would not be very emacs-like to do
M-x xml-insert/document RET and to be prompted for half a hour to
insert a whole document.  Instead, you could do something like
customize-variable.   Try for example M-x customize-variable RET
lisp-source-modes RET Most of the buffer is read-only, and there are
left some area you can edit.  There are some buttons, to insert or
remove repeatitive areas.  You could have a look at the sources of
customize-variable to see how it's done and implement your structural
editor like this.


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

THIS IS A 100% MATTER PRODUCT: In the unlikely event that this
merchandise should contact antimatter in any form, a catastrophic
explosion will result.


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Using setq to obtain a symbol from a list, so that I can assign a  function to it
  2008-04-22 19:59 ` Pascal Bourguignon
@ 2008-04-23  3:11   ` Timothy Hobbs
       [not found]   ` <mailman.10727.1208920326.18990.help-gnu-emacs@gnu.org>
  1 sibling, 0 replies; 16+ messages in thread
From: Timothy Hobbs @ 2008-04-23  3:11 UTC (permalink / raw)
  To: EMACS list

Pascal Bourguignon <pjb@informatimago.com> writes:
> but it's probably better to but these function in a hash-table than in
> the value slots of the symbols.
I am curious, why would this be better?  I find that when an elisp program defines functions outside of the standard lisp symbols reading and modifying them becomes difficult or impossible.  In the simplest scenario, simply finding out how functionality is implemented, I cannot use C-h f to jump to the doc string and ultimately, through that handy little hyperlink, source code.  In a more involved case, I cannot advise, or redefine the function.

> Finally, emacs is not modal.  It would not be very emacs-like to do
> M-x xml-insert/document RET and to be prompted for half a hour to
> insert a whole document.  Instead, you could do something like
> customize-variable.   Try for example M-x customize-variable RET
> lisp-source-modes RET Most of the buffer is read-only, and there are
> left some area you can edit.  There are some buttons, to insert or
> remove repeatitive areas.  You could have a look at the sources of
> customize-variable to see how it's done and implement your structural
> editor like this.

I just thought I would endose msf-abbrev-mode here.

Thank you

Timothy Hobbs




^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Using setq to obtain a symbol from a list, so that I can assign a  function to it
       [not found]   ` <mailman.10727.1208920326.18990.help-gnu-emacs@gnu.org>
@ 2008-04-23  4:06     ` Barry Margolin
  0 siblings, 0 replies; 16+ messages in thread
From: Barry Margolin @ 2008-04-23  4:06 UTC (permalink / raw)
  To: help-gnu-emacs

In article <mailman.10727.1208920326.18990.help-gnu-emacs@gnu.org>,
 Timothy Hobbs <tim.thelion@gmail.com> wrote:

> Pascal Bourguignon <pjb@informatimago.com> writes:
> > but it's probably better to but these function in a hash-table than in
> > the value slots of the symbols.
> I am curious, why would this be better?  I find that when an elisp program 
> defines functions outside of the standard lisp symbols reading and modifying 
> them becomes difficult or impossible.  In the simplest scenario, simply 
> finding out how functionality is implemented, I cannot use C-h f to jump to 
> the doc string and ultimately, through that handy little hyperlink, source 
> code.  In a more involved case, I cannot advise, or redefine the function.

Most of these things are unlikely to be done for dynamically-generated 
functions that are internal to an application like this.  There's no 
source code for that "handy little hyperlink" to point to, because the 
function was created on the fly.

-- 
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Using setq to obtain a symbol from a list, so that I can assign a function to it
  2008-04-22 12:54   ` Barry Margolin
@ 2008-04-23  4:40     ` srinik001
  2008-04-23 22:14       ` Pascal Bourguignon
  2008-04-24  2:50       ` Barry Margolin
  0 siblings, 2 replies; 16+ messages in thread
From: srinik001 @ 2008-04-23  4:40 UTC (permalink / raw)
  To: help-gnu-emacs

On Apr 22, 5:54 am, Barry Margolin <bar...@alum.mit.edu> wrote:
> In article
> <a4bb6deb-6337-43bd-95e4-64a29770c...@y18g2000pre.googlegroups.com>,
>
>  srinik...@hotmail.com wrote:
> > Oops... I got the subject wrong. Instead of
>
> > " Using setq to obtain a symbol from a list, so that I can assign a
> > function to it", it should read, "Using setq to assign value to the
> > result of a function". Sorry about that.
>
> Use set instead of setq.
>
> --
> Barry Margolin, bar...@alum.mit.edu
> Arlington, MA
> *** PLEASE post questions in newsgroups, not directly to me ***
> *** PLEASE don't copy me on replies, I'll read them in the group ***

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.

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. 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.

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.

Thanks,

Regards,

SK


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Using setq to obtain a symbol from a list, so that I can assign a function to it
  2008-04-22  5:19 ` srinik001
  2008-04-22 12:54   ` Barry Margolin
@ 2008-04-23  5:10   ` Kevin Rodgers
       [not found]   ` <mailman.10729.1208927476.18990.help-gnu-emacs@gnu.org>
  2 siblings, 0 replies; 16+ messages in thread
From: Kevin Rodgers @ 2008-04-23  5:10 UTC (permalink / raw)
  To: help-gnu-emacs

srinik001@hotmail.com wrote:
> Oops... I got the subject wrong. Instead of
> 
> " Using setq to obtain a symbol from a list, so that I can assign a
> function to it", it should read, "Using setq to assign value to the
> result of a function". Sorry about that.

Use set instead of setq:

,----[ C-h f setq RET ]
| setq is a special form in `C source code'.
| (setq [sym val]...)
|
| Set each sym to the value of its val.
| The symbols sym are variables; they are literal (not evaluated).
| The values val are expressions; they are evaluated.
| Thus, (setq x (1+ y)) sets `x' to the value of `(1+ y)'.
| The second val is not computed until after the first sym is set, and 
so on;
| each val can use the new value of variables set earlier in the `setq'.
| The return value of the `setq' form is the value of the last val.
|
| [back]
`----

,----[ C-h f set RET ]
| set is a built-in function in `C source code'.
| (set symbol newval)
|
| Set symbol's value to newval, and return newval.
|
| [back]
`----

-- 
Kevin Rodgers
Denver, Colorado, USA





^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Using setq to obtain a symbol from a list, so that I can assign a  function to it
  2008-04-23  4:40     ` srinik001
@ 2008-04-23 22:14       ` Pascal Bourguignon
  2008-04-24  2:50       ` Barry Margolin
  1 sibling, 0 replies; 16+ messages in thread
From: Pascal Bourguignon @ 2008-04-23 22:14 UTC (permalink / raw)
  To: help-gnu-emacs


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.


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Using setq to obtain a symbol from a list, so that I can assign a function to it
  2008-04-23  4:40     ` srinik001
  2008-04-23 22:14       ` Pascal Bourguignon
@ 2008-04-24  2:50       ` Barry Margolin
  2008-04-28  1:03         ` srinik001
  1 sibling, 1 reply; 16+ messages in thread
From: Barry Margolin @ 2008-04-24  2:50 UTC (permalink / raw)
  To: help-gnu-emacs

In article 
<530940ca-d019-42d4-ba15-c8674a8eb858@59g2000hsb.googlegroups.com>,
 srinik001@hotmail.com wrote:

> On Apr 22, 5:54 am, Barry Margolin <bar...@alum.mit.edu> wrote:
> > In article
> > <a4bb6deb-6337-43bd-95e4-64a29770c...@y18g2000pre.googlegroups.com>,
> >
> >  srinik...@hotmail.com wrote:
> > > Oops... I got the subject wrong. Instead of
> >
> > > " Using setq to obtain a symbol from a list, so that I can assign a
> > > function to it", it should read, "Using setq to assign value to the
> > > result of a function". Sorry about that.
> >
> > Use set instead of setq.
> >
> > --
> > Barry Margolin, bar...@alum.mit.edu
> > Arlington, MA
> > *** PLEASE post questions in newsgroups, not directly to me ***
> > *** PLEASE don't copy me on replies, I'll read them in the group ***
> 
> 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.
> 
> 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. 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.

There are several things wrong here.

First, you're effectively doing:

(setq subject ...)

and then

(funcall 'subject)

But funcall expects subject to be a function name, not a variable name.  
What you probably want to do is:

(setf (symbol-function (car x)) ...)

The other problem is that you're not even assigning a function.  You're 
setting subject to the return value of dolist, which is just nil.  I'm 
not really sure how to recode what you're doing to get this right.

You're obviously trying to write a parser-generator in Lisp.  This has 
been done many times, I suggest you check Lisp code repositories, and 
see how they've done it.

-- 
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Using setq to obtain a symbol from a list, so that I can assign a function to it
  2008-04-24  2:50       ` Barry Margolin
@ 2008-04-28  1:03         ` srinik001
  0 siblings, 0 replies; 16+ messages in thread
From: srinik001 @ 2008-04-28  1:03 UTC (permalink / raw)
  To: help-gnu-emacs


>
> The other problem is that you're not even assigning a function.  You're
> setting subject to the return value of dolist, which is just nil.  I'm
> not really sure how to recode what you're doing to get this right.
>
> You're obviously trying to write a parser-generator in Lisp.  This has
> been done many times, I suggest you check Lisp code repositories, and
> see how they've done it.
>
> --
> Barry Margolin, bar...@alum.mit.edu

Thanks, Barry and Pascal.

Actually, I had something in mind far less ambitious than writing a
parser-generator. I was trying to get it to do prompting, not parsing.
That is, if I gave it a grammar like the one I posted, having coded
the leaf-level functions by hand, I wanted to be able to enter the
command "sentence" and have Emacs prompt me for subject, article etc.,
that is, lead me through the creation of an XML file without errors,
without my having to remember what attributes made up a tag, what tag
was contained within what tag etc.

I certainly don't want to be writing a parser until I have a very good
grasp of Lisp, which I don't at this point.

Regards,

SK


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Using setq to obtain a symbol from a list, so that I can assign a function to it
       [not found]   ` <mailman.10729.1208927476.18990.help-gnu-emacs@gnu.org>
@ 2008-05-17 22:14     ` David Combs
  2008-05-20  2:42       ` Kevin Rodgers
  0 siblings, 1 reply; 16+ messages in thread
From: David Combs @ 2008-05-17 22:14 UTC (permalink / raw)
  To: help-gnu-emacs

In article <mailman.10729.1208927476.18990.help-gnu-emacs@gnu.org>,
Kevin Rodgers  <kevin.d.rodgers@gmail.com> wrote:
>srinik001@hotmail.com wrote:
>> Oops... I got the subject wrong. Instead of
>> 
>> " Using setq to obtain a symbol from a list, so that I can assign a
>> function to it", it should read, "Using setq to assign value to the
>> result of a function". Sorry about that.
>
>Use set instead of setq:
>
>,----[ C-h f setq RET ]
>| setq is a special form in `C source code'.
>| (setq [sym val]...)
>|
>| Set each sym to the value of its val.
>| The symbols sym are variables; they are literal (not evaluated).
>| The values val are expressions; they are evaluated.
>| Thus, (setq x (1+ y)) sets `x' to the value of `(1+ y)'.
>| The second val is not computed until after the first sym is set, and 
>so on;
>| each val can use the new value of variables set earlier in the `setq'.
>| The return value of the `setq' form is the value of the last val.
>|
>| [back]
>`----
>
>,----[ C-h f set RET ]
>| set is a built-in function in `C source code'.
>| (set symbol newval)
>|
>| Set symbol's value to newval, and return newval.
>|
>| [back]
>`----
>
>-- 
>Kevin Rodgers
>Denver, Colorado, USA
>
>
>

Kevin, could you elaborate on that just a bit, on why
setq is *not* the right thing to use.

And, in general, when *do* you use plain set?


THANKS!

David




^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Using setq to obtain a symbol from a list, so that I can assign a  function to it
  2008-04-22 18:36   ` Pascal Bourguignon
@ 2008-05-17 22:20     ` David Combs
  0 siblings, 0 replies; 16+ messages in thread
From: David Combs @ 2008-05-17 22:20 UTC (permalink / raw)
  To: help-gnu-emacs

In article <874p9twxc3.fsf@hubble.informatimago.com>,
Pascal Bourguignon  <pjb@informatimago.com> wrote:
>Ted Zlatanov <tzz@lifelogs.com> writes:
>
>> On Mon, 21 Apr 2008 19:28:03 -0700 (PDT) srinik001@hotmail.com wrote: 
>>
>> s> So, I am trying to write a tool that will enable me to write specific
>> s> XML files by prompting me to enter values. Here is how I am trying to
>> s> do it.
>>
>> You may want to look at the various templating packages available, in
>> case one of them does what you want.  Check out skeleton.el in
>> particular (http://www.emacswiki.org/cgi-bin/wiki/SkeletonMode for some
>> examples) since any element of the template can itself be a template.
>> That will probably save you a lot of time.
>>
>> Anytime you find yourself auto-generating functions you should wonder if
>> your data structure could be better (sometimes the answer is 'no' :)
>
>Well, I wouldn't be so categoric.  You could start by writting an
>"interpreter" of your data, but generating lisp is like implementing
>the "compiler", so I don't see much difference.  It's so easy to do it
>in lisp, that you can go directly to the "compiler".
>
>-- 
>__Pascal Bourguignon__                     http://www.informatimago.com/

Pascal,

If by chance you have (tutorial?) examples of this idea perhaps you
could post them here, or point us to a site (one of yours?) that
does have such tutorial examples.

Of course various text-books contain an example or two, via hairy
(*extremely* hairy) macros, but it'd be nice to see a whole bunch
in one place, compared, and so on.

As I understand it, lisp is *the* language for doing such things --
or has that changed over the years with the introduction (decades ago)
of various functional languages?


Thanks!

David




^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Using setq to obtain a symbol from a list, so that I can assign a function to it
  2008-05-17 22:14     ` David Combs
@ 2008-05-20  2:42       ` Kevin Rodgers
  0 siblings, 0 replies; 16+ messages in thread
From: Kevin Rodgers @ 2008-05-20  2:42 UTC (permalink / raw)
  To: help-gnu-emacs

David Combs wrote:
> In article <mailman.10729.1208927476.18990.help-gnu-emacs@gnu.org>,
> Kevin Rodgers  <kevin.d.rodgers@gmail.com> wrote:
>> srinik001@hotmail.com wrote:
>>> Oops... I got the subject wrong. Instead of
>>>
>>> " Using setq to obtain a symbol from a list, so that I can assign a
>>> function to it", it should read, "Using setq to assign value to the
>>> result of a function". Sorry about that.
>> Use set instead of setq:
>>
>> ,----[ C-h f setq RET ]
>> | setq is a special form in `C source code'.
>> | (setq [sym val]...)
>> |
>> | Set each sym to the value of its val.
>> | The symbols sym are variables; they are literal (not evaluated).
>> | The values val are expressions; they are evaluated.
>> | Thus, (setq x (1+ y)) sets `x' to the value of `(1+ y)'.
>> | The second val is not computed until after the first sym is set, and 
>> so on;
>> | each val can use the new value of variables set earlier in the `setq'.
>> | The return value of the `setq' form is the value of the last val.
>> |
>> | [back]
>> `----
>>
>> ,----[ C-h f set RET ]
>> | set is a built-in function in `C source code'.
>> | (set symbol newval)
>> |
>> | Set symbol's value to newval, and return newval.
>> |
>> | [back]
>> `----
> 
> Kevin, could you elaborate on that just a bit, on why
> setq is *not* the right thing to use.
> 
> And, in general, when *do* you use plain set?

If I recall, the symbol whose value you want to set came from some data
structure, the list mentioned in the subject.  Since you don't know what
that symbol is ahead of time, you can't use setq: setq is a special form
that does not evaluate its SYMBOL argument, but sets that literal
SYMBOL.

On the other hand, set is a true function, meaning that all its
arguments are evaluated before the function itself is called.  So you
can write any expression that evaluates to a symbol as its first
argument.

Hope that helps,


-- 
Kevin Rodgers
Denver, Colorado, USA





^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2008-05-20  2:42 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-04-22  2:28 Using setq to obtain a symbol from a list, so that I can assign a function to it srinik001
2008-04-22  5:19 ` srinik001
2008-04-22 12:54   ` Barry Margolin
2008-04-23  4:40     ` srinik001
2008-04-23 22:14       ` Pascal Bourguignon
2008-04-24  2:50       ` Barry Margolin
2008-04-28  1:03         ` srinik001
2008-04-23  5:10   ` Kevin Rodgers
     [not found]   ` <mailman.10729.1208927476.18990.help-gnu-emacs@gnu.org>
2008-05-17 22:14     ` David Combs
2008-05-20  2:42       ` Kevin Rodgers
2008-04-22 15:22 ` Ted Zlatanov
2008-04-22 18:36   ` Pascal Bourguignon
2008-05-17 22:20     ` David Combs
2008-04-22 19:59 ` Pascal Bourguignon
2008-04-23  3:11   ` Timothy Hobbs
     [not found]   ` <mailman.10727.1208920326.18990.help-gnu-emacs@gnu.org>
2008-04-23  4:06     ` Barry Margolin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).