From: Berk Birand
Subject: Naming macros and functions from symbols
Date: 
Message-ID: <pan.2006.09.04.21.58.20.197833@yahoo.com>
Hi,

I'm somewhat new to LISP, and for a project of mine I need to make use of
a feature that seems a little to advanced for my knowledge. I want to be
able to read some data from a file, and define functions and macros based
on the data from the file. Since the file is structured for lisp, I can
simply use read to do that. But then, when I try to do something like 

;; will be passed to mapcar
;; function name will come from the first entry in the argument lst (first
lst)
(defun map-pred (lst)
   (defmacro (symbol-value (first lst)) ()
    (if (eql (symbol-value (second lst)) (symbol-value (third lst)))
     (princ "It is green!!"))))

So when called as in (map-pred '(green? green t)), i want it to define the
macro
(green?)
which has the body:
(if (eql green t) (princ "green!")))

When trying to interpret this, lisp complains:

*** - The name of a macro must be a symbol, not (SYMBOL-VALUE (FIRST LST))

Is there a way to do this (I'm sure there is, it's LISP after all right?)

Thanks for your replies,
Berk Birand

-- 
Posted via a free Usenet account from http://www.teranews.com

From: Ari Johnson
Subject: Re: Naming macros and functions from symbols
Date: 
Message-ID: <m2mz9fmk8n.fsf@nibbler.theari.com>
Berk Birand <········@yahoo.com> writes:

> Hi,
>
> I'm somewhat new to LISP, and for a project of mine I need to make use of
> a feature that seems a little to advanced for my knowledge. I want to be
> able to read some data from a file, and define functions and macros based
> on the data from the file. Since the file is structured for lisp, I can
> simply use read to do that. But then, when I try to do something like 
>
> ;; will be passed to mapcar
> ;; function name will come from the first entry in the argument lst (first
> lst)
> (defun map-pred (lst)
>    (defmacro (symbol-value (first lst)) ()
>     (if (eql (symbol-value (second lst)) (symbol-value (third lst)))
>      (princ "It is green!!"))))
>
> So when called as in (map-pred '(green? green t)), i want it to define the
> macro
> (green?)
> which has the body:
> (if (eql green t) (princ "green!")))
>
> When trying to interpret this, lisp complains:
>
> *** - The name of a macro must be a symbol, not (SYMBOL-VALUE (FIRST LST))
>
> Is there a way to do this (I'm sure there is, it's LISP after all right?)

Defining a macro from things you read in can only be done by way of
EVAL or COMPILE, both with respect to the macro definition and with
respect to its application to data.  As long as you already have to
use EVAL or COMPILE, why not write a function that transforms (I avoid
the word "compiles" here to avoid confusion with the COMPILE operator)
the incoming data into Lisp code that can then be run through EVAL (or
through COMPILE if stuffed into a LAMBDA form) to produce the desired
results?
From: Juho Snellman
Subject: Re: Naming macros and functions from symbols
Date: 
Message-ID: <slrnefp63g.fls.jsnell@sbz-30.cs.Helsinki.FI>
Ari Johnson <·········@gmail.com> wrote:
> Berk Birand <········@yahoo.com> writes:
[...]
>> (defun map-pred (lst)
>>    (defmacro (symbol-value (first lst)) ()
>>     (if (eql (symbol-value (second lst)) (symbol-value (third lst)))
>>      (princ "It is green!!"))))
>>
>> So when called as in (map-pred '(green? green t)), i want it to define the
>> macro
>> (green?)
>> which has the body:
>> (if (eql green t) (princ "green!")))
[...]
> Defining a macro from things you read in can only be done by way of
> EVAL or COMPILE, both with respect to the macro definition and with
> respect to its application to data.

No, you just need (SETF MACRO-FUNCTION) and closures for that. To 
illustrate with the above case:

* (defun map-pred (args)           
     (destructuring-bind (fun-name var-name value) args
        (setf (macro-function fun-name)
              (lambda (whole env)
                (declare (ignore whole env))
                `(when (eql ,var-name ,value)
                   (princ "It is green!!"))))))

MAP-PRED
* (map-pred '(green? green t))

#<CLOSURE (LAMBDA (WHOLE ENV)) {1002598A99}>
* (macroexpand-1 '(green?))

(WHEN (EQL GREEN T) (PRINC "It is green!!"))
T

-- 
Juho Snellman
From: Ari Johnson
Subject: Re: Naming macros and functions from symbols
Date: 
Message-ID: <m2d5abjokj.fsf@hermes.theari.com>
Juho Snellman <······@iki.fi> writes:

> Ari Johnson <·········@gmail.com> wrote:
>> Berk Birand <········@yahoo.com> writes:
> [...]
>>> (defun map-pred (lst)
>>>    (defmacro (symbol-value (first lst)) ()
>>>     (if (eql (symbol-value (second lst)) (symbol-value (third lst)))
>>>      (princ "It is green!!"))))
>>>
>>> So when called as in (map-pred '(green? green t)), i want it to define the
>>> macro
>>> (green?)
>>> which has the body:
>>> (if (eql green t) (princ "green!")))
> [...]
>> Defining a macro from things you read in can only be done by way of
>> EVAL or COMPILE, both with respect to the macro definition and with
>> respect to its application to data.
>
> No, you just need (SETF MACRO-FUNCTION) and closures for that. To 
> illustrate with the above case:
>
> * (defun map-pred (args)           
>      (destructuring-bind (fun-name var-name value) args
>         (setf (macro-function fun-name)
>               (lambda (whole env)
>                 (declare (ignore whole env))
>                 `(when (eql ,var-name ,value)
>                    (princ "It is green!!"))))))
>
> MAP-PRED
> * (map-pred '(green? green t))
>
> #<CLOSURE (LAMBDA (WHOLE ENV)) {1002598A99}>
> * (macroexpand-1 '(green?))
>
> (WHEN (EQL GREEN T) (PRINC "It is green!!"))
> T

Okay, fair enough.  But you still need to compile or EVAL the
resulting form of the macro expansion, so change 'both ... and' to
'either ... or' in my previous message.  You still don't seem to gain
much over compiling the incoming data to a closure in a more
straightforward, functional way.
From: Pascal Bourguignon
Subject: Re: Naming macros and functions from symbols
Date: 
Message-ID: <87fyf79spb.fsf@thalassa.informatimago.com>
Berk Birand <········@yahoo.com> writes:

> Hi,
>
> I'm somewhat new to LISP, and for a project of mine I need to make use of
> a feature that seems a little to advanced for my knowledge. I want to be
> able to read some data from a file, and define functions and macros based
> on the data from the file. Since the file is structured for lisp, I can
> simply use read to do that. But then, when I try to do something like 
>
> ;; will be passed to mapcar
> ;; function name will come from the first entry in the argument lst (first
> lst)
> (defun map-pred (lst)
>    (defmacro (symbol-value (first lst)) ()
>     (if (eql (symbol-value (second lst)) (symbol-value (third lst)))
>      (princ "It is green!!"))))
>
> So when called as in (map-pred '(green? green t)), i want it to define the
> macro
> (green?)
> which has the body:
> (if (eql green t) (princ "green!")))
>
> When trying to interpret this, lisp complains:
>
> *** - The name of a macro must be a symbol, not (SYMBOL-VALUE (FIRST LST))
>
> Is there a way to do this (I'm sure there is, it's LISP after all right?)

You are not having a macro problem. You're having a mere list building
problem.

How do you build a list that have the symbol DEFPMACRO as first element,
and the first symbol of LST as second element, 
and NIL as third element, 
and a list whose first element is IF as fourth element?


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
Until real software engineering is developed, the next best practice
is to develop with a dynamic system that has extreme late binding in
all aspects. The first system to really do this in an important way
is Lisp. -- Alan Kay
From: Thomas A. Russ
Subject: Re: Naming macros and functions from symbols
Date: 
Message-ID: <ymilkoy9jcv.fsf@sevak.isi.edu>
Berk Birand <········@yahoo.com> writes:

> Hi,
> 
> I'm somewhat new to LISP, and for a project of mine I need to make use of
> a feature that seems a little to advanced for my knowledge. I want to be
> able to read some data from a file, and define functions and macros based
> on the data from the file. Since the file is structured for lisp, I can
> simply use read to do that. But then, when I try to do something like 
> 
> ;; will be passed to mapcar
> ;; function name will come from the first entry in the argument lst (first
> lst)
> (defun map-pred (lst)
>    (defmacro (symbol-value (first lst)) ()
>     (if (eql (symbol-value (second lst)) (symbol-value (third lst)))
>      (princ "It is green!!"))))
>
> So when called as in (map-pred '(green? green t)), i want it to define the
> macro
> (green?)
> which has the body:
> (if (eql green t) (princ "green!")))

OK.  The first question I have is why you need the resulting item to be
a macro.  

Looking at the body, it seems that the reason you want a macro is to use
some sort of variable capture on the symbol named GREEN.  Although lisp
allows you to do this, it is almost always a Bad Idea(tm), and should
generally be avoided.

Particularly with someone new to Lisp, this is the point where the
veterans generally ask you to explain at a higher level what you are
trying to accomplish, since there is often a cleaner and more idiomatic
way of solving the problem in Lisp.

So:
  What do you want to do with the data in the file?

  It seems that you use it to define some predicates.
  What do you then use the predicates for?

  Do you have control over the format of the input file?


In regards to the later, if you have control over the input file format
then you could make a minor change to the format to include a definition
form (which is implemented as a macro) that would accomplish what you
want.  In other words, you could write the "data" file like:

  (defpredicate green? green t)
  (defpredicate yellow? yellow t)

and then write something like

  (defmacro defpredicate (name variable value)
    `(defmacro ,name ()
       (if (eql ,variable ,value)
          (princ "green!"))))

except that this seems to be a bit too specific, since you probably
don't want to hard-code the action to take in the generation function of
the macro.

This, leads again to the main question:  What are you really trying to do?



-- 
Thomas A. Russ,  USC/Information Sciences Institute