From: Vijay L
Subject: macros with evaluated arguments
Date: 
Message-ID: <1eaf81aa.0208130244.2946fa46@posting.google.com>
Hello everyone,
I've written a recursive-decsent parser generator. it accepts a
grammar and creates a function for each non-terminal in the grammar, a
parser and a kind of lexical analyzer.

its arguments are like this:
(make-rdp ((?S ?A ?B) ;nonterminals
           (a b c d)  ;terminals
           ?S         ;start symbol
           ((?S a ?S ?A) ;productions
            (?S c c)
            (?A ?B b)
            (?b d d)))

i'd like to know if it is possible to simply call the macro thus:
(make-rdp grammar)
where `grammar' contains the grammar specified above.

Thanks,
Vijay L

From: Nils Goesche
Subject: Re: macros with evaluated arguments
Date: 
Message-ID: <lk7kivm3av.fsf@pc022.bln.elmeg.de>
······@lycos.com (Vijay L) writes:

> Hello everyone,
> I've written a recursive-decsent parser generator. it accepts a
> grammar and creates a function for each non-terminal in the grammar, a
> parser and a kind of lexical analyzer.
> 
> its arguments are like this:
> (make-rdp ((?S ?A ?B) ;nonterminals
>            (a b c d)  ;terminals
>            ?S         ;start symbol
>            ((?S a ?S ?A) ;productions
>             (?S c c)
>             (?A ?B b)
>             (?b d d)))
> 
> i'd like to know if it is possible to simply call the macro thus:
> (make-rdp grammar)
> where `grammar' contains the grammar specified above.

Apparently MAKE-RDP parses its argument directly.  In that case, you
can still do (make-rdp #.grammar), but only if grammar is known at
compile time (which you can ensure with EVAL-WHEN).

Regards,
-- 
Nils Goesche
"Don't ask for whom the <CTRL-G> tolls."

PGP key ID 0x42B32FC9
From: Barry Margolin
Subject: Re: macros with evaluated arguments
Date: 
Message-ID: <fE869.5$DM3.1743@paloalto-snr1.gtei.net>
In article <····························@posting.google.com>,
Vijay L <······@lycos.com> wrote:
>Hello everyone,
>I've written a recursive-decsent parser generator. it accepts a
>grammar and creates a function for each non-terminal in the grammar, a
>parser and a kind of lexical analyzer.
>
>its arguments are like this:
>(make-rdp ((?S ?A ?B) ;nonterminals
>           (a b c d)  ;terminals
>           ?S         ;start symbol
>           ((?S a ?S ?A) ;productions
>            (?S c c)
>            (?A ?B b)
>            (?b d d)))
>
>i'd like to know if it is possible to simply call the macro thus:
>(make-rdp grammar)
>where `grammar' contains the grammar specified above.

If you wanted to be able to do this, why did you define it as a macro in
the first place?  You should define it as a function, and then if you want
a macro interface it's simple to add:

(defmacro defrdp (grammar)
  `(make-rdp ',grammar))

Given that you have a macro, you can use EVAL to invoke it with evaluated
arguments:

(eval `(make-rdp ,grammar))

-- 
Barry Margolin, ······@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Vijay L
Subject: Re: macros with evaluated arguments
Date: 
Message-ID: <1eaf81aa.0208142149.1e2477f@posting.google.com>
Barry Margolin <······@genuity.net> wrote in message news:<················@paloalto-snr1.gtei.net>...
> In article <····························@posting.google.com>,
> Vijay L <······@lycos.com> wrote:
> >Hello everyone,
> >I've written a recursive-decsent parser generator. it accepts a
> >grammar and creates a function for each non-terminal in the grammar, a
> >parser and a kind of lexical analyzer.
> >
> >its arguments are like this:
> >(make-rdp ((?S ?A ?B) ;nonterminals
> >           (a b c d)  ;terminals
> >           ?S         ;start symbol
> >           ((?S a ?S ?A) ;productions
> >            (?S c c)
> >            (?A ?B b)
> >            (?b d d)))
> >
> >i'd like to know if it is possible to simply call the macro thus:
> >(make-rdp grammar)
> >where `grammar' contains the grammar specified above.
> 
> If you wanted to be able to do this, why did you define it as a macro in
> the first place?  You should define it as a function, and then if you want
> a macro interface it's simple to add:
> 
> (defmacro defrdp (grammar)
>   `(make-rdp ',grammar))

I cannot do the above because the macro generates code. For eg.

(pprint
 (macroexpand-1
  '(make-parser ( ;grammar that accepts all strings with an odd
                  ;number of 1s [ones]
                 (?s ?a)
                 (1)
                 ?s
                 ((?s 1 ?a)
                  (?a 1 ?s)
                  (?a nil) ;nil is epsilon
                  )))))

i have changed the resulting code to lower case

(progn
  (defvar *current-token* ())
  (defvar *sentence* ())
  (defvar *grammar* (quote
                           ((?s ?a)
                            (1)
                            ?s
                            ((?s 1 ?a) (?a 1 ?s) (?a nil)))))
  (defun next-token ()
    (setf *current-token* (pop *sentence*)))
  (defun restore (sentence token)
    (setf *sentence* sentence
          *current-token* token)
    'nil)
  (defun ?a ()
    (let ((save-sent *sentence*)
          (save-ct *current-token*))
      (cond ((cond ((eq *current-token* '1)
                    (next-token)
                    (cond ((?s) t)
                          (t (restore save-sent save-ct))))
                   (t (restore save-sent save-ct))))
            ((cond (t t) (t (restore save-sent save-ct)))))))
  (defun ?s ()
    (let ((save-sent *sentence*)
          (save-ct *current-token*))
      (cond ((cond ((eq *current-token* '1)
                    (next-token)
                    (cond ((?a) t)
                          (t (restore save-sent save-ct))))
                   (t (restore save-sent save-ct)))))))
  (defun parse (sentence)
    (setq *sentence* sentence)
    (next-token)
    (?S)))

> Given that you have a macro, you can use EVAL to invoke it with evaluated
> arguments:
> 
> (eval `(make-rdp ,grammar))

Sir, in your article (ALU: Lisp Programming Style) you say:

EVAL. Novices almost always misuse EVAL. When experts use EVAL, they
often would be better off using APPLY, FUNCALL, or SYMBOL-VALUE. Use
of EVAL when defining a macro should set off a warning bell -- macro
definitions are already evaluated during expansion. See also the
answer to question 3-12. The general rule of thumb about EVAL is: if
you think you need to use EVAL, you're probably wrong.

given that I am a novice, and you an expert, the use of EVAL is
obviously justified here. Can you tell me when and where the use of
EVAL *is* justified or, show me a reference where I may find such
material or, does something like this grow only with experience?

Thanks,
Vijay
From: Barry Margolin
Subject: Re: macros with evaluated arguments
Date: 
Message-ID: <g%O69.6$%V3.656@paloalto-snr1.gtei.net>
In article <···························@posting.google.com>,
Vijay L <······@lycos.com> wrote:
>Barry Margolin <······@genuity.net> wrote in message
>news:<················@paloalto-snr1.gtei.net>...
>> If you wanted to be able to do this, why did you define it as a macro in
>> the first place?  You should define it as a function, and then if you want
>> a macro interface it's simple to add:
>> 
>> (defmacro defrdp (grammar)
>>   `(make-rdp ',grammar))
>
>I cannot do the above because the macro generates code. For eg.

You wrote it, you can fix that, can't you?  Instead of generating

(defun next-token ()
  (setf *current-token* (pop *sentence*)))

it can execute:

(setf (symbol-function 'next-token)
      #'(lambda () (setf *current-token* (pop *sentence*))))

>Sir, in your article (ALU: Lisp Programming Style) you say:
>
>EVAL. Novices almost always misuse EVAL. When experts use EVAL, they
>often would be better off using APPLY, FUNCALL, or SYMBOL-VALUE. Use
>of EVAL when defining a macro should set off a warning bell -- macro
>definitions are already evaluated during expansion. See also the

In this case you're not using it in the definition of the macro.

>answer to question 3-12. The general rule of thumb about EVAL is: if
>you think you need to use EVAL, you're probably wrong.

But one of the few appropriate uses of EVAL is to supply runtime-generated
data to something that's only available as a macro.

-- 
Barry Margolin, ······@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Vijay L
Subject: Re: macros with evaluated arguments
Date: 
Message-ID: <1eaf81aa.0208151947.6542c00a@posting.google.com>
Barry Margolin <······@genuity.net> wrote in message news:<g%O69.6$%> 
> You wrote it, you can fix that, can't you?  Instead of generating
> 
> (defun next-token ()
>   (setf *current-token* (pop *sentence*)))
> 
> it can execute:
> 
> (setf (symbol-function 'next-token)
>       #'(lambda () (setf *current-token* (pop *sentence*))))

If I do that, will I be able to compile the functions `generated' so?
Any function defined by DEFUN is available in global scope, will a
function defined the above specified way also be available the same
way?

> >Sir, in your article (ALU: Lisp Programming Style) you say:
> >
> >EVAL. Novices almost always misuse EVAL. When experts use EVAL, they
> >often would be better off using APPLY, FUNCALL, or SYMBOL-VALUE. Use
> >of EVAL when defining a macro should set off a warning bell -- macro
> >definitions are already evaluated during expansion. See also the
> 
> In this case you're not using it in the definition of the macro.
> 
> >answer to question 3-12. The general rule of thumb about EVAL is: if
> >you think you need to use EVAL, you're probably wrong.
> 
> But one of the few appropriate uses of EVAL is to supply runtime-generated
> data to something that's only available as a macro.

Thank you.


Thanks,
Vijay L
From: Barry Margolin
Subject: Re: macros with evaluated arguments
Date: 
Message-ID: <xF879.4$%k.1072@paloalto-snr1.gtei.net>
In article <····························@posting.google.com>,
Vijay L <······@lycos.com> wrote:
>Barry Margolin <······@genuity.net> wrote in message news:<g%O69.6$%> 
>> You wrote it, you can fix that, can't you?  Instead of generating
>> 
>> (defun next-token ()
>>   (setf *current-token* (pop *sentence*)))
>> 
>> it can execute:
>> 
>> (setf (symbol-function 'next-token)
>>       #'(lambda () (setf *current-token* (pop *sentence*))))
>
>If I do that, will I be able to compile the functions `generated' so?

Yes, the functions will be compiled when the function containing the
assignment is compiled.  E.g. if you have:

(defun make-adder (x)
  #'(lambda (y) (+ x y)))

when you compile MAKE-ADDER, the function that will be included in the
closures that it returns will also be compiled.

>Any function defined by DEFUN is available in global scope, will a
>function defined the above specified way also be available the same
>way?

SETF of SYMBOL-FUNCTION updates the symbol's global function binding.

-- 
Barry Margolin, ······@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Thomas F. Burdick
Subject: Re: macros with evaluated arguments
Date: 
Message-ID: <xcvhehuk7v1.fsf@mudslide.OCF.Berkeley.EDU>
Barry Margolin <······@genuity.net> writes:

> In article <····························@posting.google.com>,
> Vijay L <······@lycos.com> wrote:
>
> >Any function defined by DEFUN is available in global scope, will a
> >function defined the above specified way also be available the same
> >way?
>
> SETF of SYMBOL-FUNCTION updates the symbol's global function binding.

The only caveat is that defining a function this way might circumvent
some niceties in your development environment.

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | No to Imperialist war |                        
     ,--'    _,'   | Wage class war!       |                        
    /       /      `-----------------------'                        
   (   -.  |                               
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Barry Margolin
Subject: Re: macros with evaluated arguments
Date: 
Message-ID: <wcb79.18$%k.3660@paloalto-snr1.gtei.net>
In article <···············@mudslide.OCF.Berkeley.EDU>,
Thomas F. Burdick <···@mudslide.OCF.Berkeley.EDU> wrote:
>Barry Margolin <······@genuity.net> writes:
>
>> In article <····························@posting.google.com>,
>> Vijay L <······@lycos.com> wrote:
>>
>> >Any function defined by DEFUN is available in global scope, will a
>> >function defined the above specified way also be available the same
>> >way?
>>
>> SETF of SYMBOL-FUNCTION updates the symbol's global function binding.
>
>The only caveat is that defining a function this way might circumvent
>some niceties in your development environment.

In many cases, the same thing happens when the function is defined as a
result of expanding a macro.

-- 
Barry Margolin, ······@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Thomas A. Russ
Subject: Re: macros with evaluated arguments
Date: 
Message-ID: <ymiofc2l64h.fsf@sevak.isi.edu>
······@lycos.com (Vijay L) writes:

> 
> Barry Margolin <······@genuity.net> wrote in message news:<g%O69.6$%> 
> > You wrote it, you can fix that, can't you?  Instead of generating
> > 
> > (defun next-token ()
> >   (setf *current-token* (pop *sentence*)))
> > 
> > it can execute:
> > 
> > (setf (symbol-function 'next-token)
> >       #'(lambda () (setf *current-token* (pop *sentence*))))
> 
> If I do that, will I be able to compile the functions `generated' so?

You can always explicitly call the compiler at runtime:

  (setf (symbol-function 'next-token)
        (compile nil
                 #'(lambda () (setf *current-token* (pop *sentence*)))))

or more succinctly by

   (compile 'next-token
            #'(lambda () (setf *current-token* (pop *sentence*))))


> Any function defined by DEFUN is available in global scope, will a
> function defined the above specified way also be available the same
> way?

Yes.

-- 
Thomas A. Russ,  USC/Information Sciences Institute          ···@isi.edu    
From: Vijay L
Subject: Re: macros with evaluated arguments
Date: 
Message-ID: <1eaf81aa.0208170424.5f96e962@posting.google.com>
Thank you everyone for your help. Thanks also to Tim Bradshaw who
replied thru email.

Thanks,
Vijay L