From: Jonathan
Subject: Macro design - is this bad?
Date: 
Message-ID: <KT7UONvn6UneTAsUaaLmFatdf0lB@4ax.com>
Hi,

I am writing probably my first set of complicated macros and have
finally finished only to find that I can't use it how I'd like to. The
macros look like this:

(defmacro build-a-func-from-file (func-and-file-name)
   `(progn
	(make-func ,(read-from-string func-and-file-name)
		 ,func-and-file-name)
	(add-func-to-arr ,(read-from-string func-and-file-name)))

(defmacro make-func (func-name file-name)
	`(defun ,func-name
	...stuff based on reading out of the file: file-name))

(defmacro add-func-to-arr (func-name)
	;; adds func-name to a list of available functions))

Now this does what I intended it to do if I run the macro with a
string argument like:

(build-a-func-from-file "test.dd")

which would read the file test.dd and then create a function named
TEST.DD based on its contents, then add this function to a list of
available built functions.

Now, I am trying to apply the build-a-func-from-file macro over a set
of files in a directory and I run into a snag that can be simplified
by this snippet:

USER(3): (setf p (pathname "test.dd"))
USER(4): (build-a-func-from-file (namestring p))
Error: the value of STRING is (NAMESTRING P), which is not of type
STRING.

This error is occuring because the argument (namestring p) is being
literally read by read-from-string; however, I cannot see a way around
this. I need to use read-from-string on the argument to turn it from a
string filename to a symbol to use in the defun later on. Have I just
made terrible choices in the design of these macros or there an easy
solution to my dilemma?

Any help or comments are appreciated.

Thanks,
Jonathan
········@ptcstudios.com

From: Rainer Joswig
Subject: Re: Macro design - is this bad?
Date: 
Message-ID: <rainer.joswig-7A01FC.09492819032000@news.is-europe.net>
In article <····························@4ax.com>, Jonathan 
<··@spam.com> wrote:

> Hi,
> 
> I am writing probably my first set of complicated macros and have
> finally finished only to find that I can't use it how I'd like to. The
> macros look like this:
> 
> (defmacro build-a-func-from-file (func-and-file-name)
>    `(progn
> 	(make-func ,(read-from-string func-and-file-name)
> 		 ,func-and-file-name)
> 	(add-func-to-arr ,(read-from-string func-and-file-name)))
> 
> (defmacro make-func (func-name file-name)
> 	`(defun ,func-name
> 	...stuff based on reading out of the file: file-name))
> 
> (defmacro add-func-to-arr (func-name)
> 	;; adds func-name to a list of available functions))
> 
> Now this does what I intended it to do if I run the macro with a
> string argument like:
> 
> (build-a-func-from-file "test.dd")
> 
> which would read the file test.dd and then create a function named
> TEST.DD based on its contents, then add this function to a list of
> available built functions.
> 
> Now, I am trying to apply the build-a-func-from-file macro over a set
> of files in a directory and I run into a snag that can be simplified
> by this snippet:
> 
> USER(3): (setf p (pathname "test.dd"))
> USER(4): (build-a-func-from-file (namestring p))
> Error: the value of STRING is (NAMESTRING P), which is not of type
> STRING.
> 
> This error is occuring because the argument (namestring p) is being
> literally read by read-from-string; however, I cannot see a way around
> this. I need to use read-from-string on the argument to turn it from a
> string filename to a symbol to use in the defun later on. Have I just
> made terrible choices in the design of these macros or there an easy
> solution to my dilemma?

Well, the DEFUN macro demands the name already as a symbol at
expansion/compile tim.
So your choices are:

- don't use DEFUN. Use (setf (symbol-function ...
  Drawback: DEFUN usually might add more bookkeeping code,
   so you might not get the other benefits of using DEFUN. 

- use an EVAL to evaluate the naming expression FUNC-AND-FILE-NAME
  in the macro at expansion time.
  Drawback: you are using EVAL.  ;-)

Rainer Joswig, ISION Internet AG, Harburger Schlossstrasse 1, 
21079 Hamburg, Germany, Tel: +49 40 77175 226
Email: ·············@ision.de , WWW: http://www.ision.de/
From: Jonathan
Subject: Re: Macro design - is this bad?
Date: 
Message-ID: <UEXVOO120nhd1hJ+CAKzoSA7baJ3@4ax.com>
Rainer,

Thank you for your suggestions; however, I am having some trouble
getting the code to work with your recommendations. In particular, I
tried implementing the EVAL statement you suggested - turning my
sample code to:

(defmacro build-a-func-from-file (func-and-file-name)
   `(progn
	(make-func ,(read-from-string (eval func-and-file-name))
		 ,func-and-file-name)
	(add-func-to-arr ,(read-from-string (func-and-file-name))))

This still does not work because the EVAL tries to evaluate an
expression like (namestring p) [see example below] at compile time,
when p will not be bound until invocation time.

Did I misinterpret your advice or is there some way around this
problem as well?

Thanks again,
Jonathan
········@ptcstudios.com

On Sun, 19 Mar 2000 09:49:28 +0100, Rainer Joswig
<·············@ision.de> wrote:

>In article <····························@4ax.com>, Jonathan 
><··@spam.com> wrote:
>
>> Hi,
>> 
>> I am writing probably my first set of complicated macros and have
>> finally finished only to find that I can't use it how I'd like to. The
>> macros look like this:
>> 
>> (defmacro build-a-func-from-file (func-and-file-name)
>>    `(progn
>> 	(make-func ,(read-from-string func-and-file-name)
>> 		 ,func-and-file-name)
>> 	(add-func-to-arr ,(read-from-string func-and-file-name)))
>> 
>> (defmacro make-func (func-name file-name)
>> 	`(defun ,func-name
>> 	...stuff based on reading out of the file: file-name))
>> 
>> (defmacro add-func-to-arr (func-name)
>> 	;; adds func-name to a list of available functions))
>> 
>> Now this does what I intended it to do if I run the macro with a
>> string argument like:
>> 
>> (build-a-func-from-file "test.dd")
>> 
>> which would read the file test.dd and then create a function named
>> TEST.DD based on its contents, then add this function to a list of
>> available built functions.
>> 
>> Now, I am trying to apply the build-a-func-from-file macro over a set
>> of files in a directory and I run into a snag that can be simplified
>> by this snippet:
>> 
>> USER(3): (setf p (pathname "test.dd"))
>> USER(4): (build-a-func-from-file (namestring p))
>> Error: the value of STRING is (NAMESTRING P), which is not of type
>> STRING.
>> 
>> This error is occuring because the argument (namestring p) is being
>> literally read by read-from-string; however, I cannot see a way around
>> this. I need to use read-from-string on the argument to turn it from a
>> string filename to a symbol to use in the defun later on. Have I just
>> made terrible choices in the design of these macros or there an easy
>> solution to my dilemma?
>
>Well, the DEFUN macro demands the name already as a symbol at
>expansion/compile tim.
>So your choices are:
>
>- don't use DEFUN. Use (setf (symbol-function ...
>  Drawback: DEFUN usually might add more bookkeeping code,
>   so you might not get the other benefits of using DEFUN. 
>
>- use an EVAL to evaluate the naming expression FUNC-AND-FILE-NAME
>  in the macro at expansion time.
>  Drawback: you are using EVAL.  ;-)
>
>Rainer Joswig, ISION Internet AG, Harburger Schlossstrasse 1, 
>21079 Hamburg, Germany, Tel: +49 40 77175 226
>Email: ·············@ision.de , WWW: http://www.ision.de/
From: Barry Margolin
Subject: Re: Macro design - is this bad?
Date: 
Message-ID: <VwsB4.34$SW5.500@burlma1-snr2>
In article <····························@4ax.com>,
Jonathan  <··@spam.com> wrote:
>Rainer,
>
>Thank you for your suggestions; however, I am having some trouble
>getting the code to work with your recommendations. In particular, I
>tried implementing the EVAL statement you suggested - turning my
>sample code to:
>
>(defmacro build-a-func-from-file (func-and-file-name)
>   `(progn
>	(make-func ,(read-from-string (eval func-and-file-name))
>		 ,func-and-file-name)
>	(add-func-to-arr ,(read-from-string (func-and-file-name))))
>
>This still does not work because the EVAL tries to evaluate an
>expression like (namestring p) [see example below] at compile time,
>when p will not be bound until invocation time.
>
>Did I misinterpret your advice or is there some way around this
>problem as well?

The point of Rainer's response was that you shouldn't be writing a macro in
the first place.  If you want to evaluate arguments, you should write
functions.

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Burlington, 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: Fernando D. Mato Mira
Subject: Re: Macro design - is this bad?
Date: 
Message-ID: <38D661D2.4A63BC9A@iname.com>
Barry Margolin wrote:

> The point of Rainer's response was that you shouldn't be writing a macro in
> the first place.  If you want to evaluate arguments, you should write
> functions.

Otherwise, it seeme to make sense only for implementing something like #include,
with the read definitions closed in the environment at the call site.

--
Fernando D. Mato Mira
Real-Time SW Eng & Networking
Advanced Systems Engineering Division
CSEM
Jaquet-Droz 1                   email: matomira AT acm DOT org
CH-2007 Neuchatel                 tel:       +41 (32) 720-5157
Switzerland                       FAX:       +41 (32) 720-5720

www.csem.ch      www.vrai.com     ligwww.epfl.ch/matomira.html
From: Rudolf Schlatte
Subject: Re: Macro design - is this bad?
Date: 
Message-ID: <lxaejueia4.fsf@ist.tu-graz.ac.at>
Jonathan <··@spam.com> writes:

> I am writing probably my first set of complicated macros and have
> finally finished only to find that I can't use it how I'd like to. The
> macros look like this:
> 
> (defmacro build-a-func-from-file (func-and-file-name)
>    `(progn
> 	(make-func ,(read-from-string func-and-file-name)
> 		 ,func-and-file-name)
> 	(add-func-to-arr ,(read-from-string func-and-file-name)))
> 

Concerning your problems with 
(build-a-func-from-file (namestring p)):
You could delay the (read-from-string ...) to run-time like this
(untested):

(defmacro build-a-func-from-file (func-and-file-name)
   `(progn
	(make-func (read-from-string ,func-and-file-name)
		 ,func-and-file-name)
	(add-func-to-arr (read-from-string ,func-and-file-name)))

> (defmacro make-func (func-name file-name)
> 	`(defun ,func-name
> 	...stuff based on reading out of the file: file-name))
> 
> (defmacro add-func-to-arr (func-name)
> 	;; adds func-name to a list of available functions))

I think this one can be a function, don't go overboard with macros...


Hope that helps,

Rudi
From: Tom Breton
Subject: Re: Macro design - is this bad?
Date: 
Message-ID: <m3og8a7gsp.fsf@world.std.com>
Jonathan <··@spam.com> writes:

> Hi,
> 
> I am writing probably my first set of complicated macros and have
> finally finished only to find that I can't use it how I'd like to. The
> macros look like this:
> 
> (defmacro build-a-func-from-file (func-and-file-name)
>    `(progn
> 	(make-func ,(read-from-string func-and-file-name)
> 		 ,func-and-file-name)
> 	(add-func-to-arr ,(read-from-string func-and-file-name)))
> 
> (defmacro make-func (func-name file-name)
> 	`(defun ,func-name
> 	...stuff based on reading out of the file: file-name))
> 
> (defmacro add-func-to-arr (func-name)
> 	;; adds func-name to a list of available functions))

Now, I haven't looked at the details, but why are they all macros?  I
mean, as opposed to just one entry point being a macro.  Are they
really each being called as macros?  Or is this, no offense intended,
a holdover from C/C++ macro thinking, where the macros are "in the
preprocessor" and have no access to normal functions?

Usually you want your macros' helper functions to be just normal
functions.  Even if they construct code fragments or something,
doesn't matter.

-- 
Tom Breton, http://world.std.com/~tob
Not using "gh" since 1997. http://world.std.com/~tob/ugh-free.html
Rethink some Lisp features, http://world.std.com/~tob/rethink-lisp/index.html
From: Pierre R. Mai
Subject: Re: Macro design - is this bad?
Date: 
Message-ID: <87hfe28krl.fsf@orion.dent.isdn.cs.tu-berlin.de>
Jonathan <··@spam.com> writes:

> Hi,
> 
> I am writing probably my first set of complicated macros and have
> finally finished only to find that I can't use it how I'd like to. The
> macros look like this:
> 
> (defmacro build-a-func-from-file (func-and-file-name)
>    `(progn
> 	(make-func ,(read-from-string func-and-file-name)
> 		 ,func-and-file-name)
> 	(add-func-to-arr ,(read-from-string func-and-file-name)))
> 
> (defmacro make-func (func-name file-name)
> 	`(defun ,func-name
> 	...stuff based on reading out of the file: file-name))
> 
> (defmacro add-func-to-arr (func-name)
> 	;; adds func-name to a list of available functions))

It seems to me that using macros to do the job you are trying to do is a
fundamentally wrong design decission.  From the names of the macros and the
code shown, it seems to me that the functionality you want to represent can
be understood in terms of run-time "environment" manipulation.  In fact
build-a-func-from file seems similar in intent and effect to LOAD and/or
COMPILE/COMPILE-FILE, with some added complexities in processing.

So reverting to normal functions, which might call out to EVAL or
COMPILE on run-time generated source to accomplish their tasks, seems
like the proper thing to do, IMHO.

(defun build-a-func-from-file (func-and-file-name)
  (let ((name (read-from-string func-and-file-name)))
    (make-func name func-and-file-name)
    (add-func-to-arr name)))

(defun make-func (func-name file-name)
  (with-open-file (stream file-name)
    (let ((lambda-form (make-lambda-form-from-stream stream)))
      ;; Either to an eval of a defun, maybe followed by a compile:
      (eval `(defun ,func-name ,(cadr lambda-form) ,@(cddr lambda-form)))
      (compile func-name)
      ;; Or maybe do compile of lambda form and setf of fdefinition
      ;; instead.  There are many other ways of doing this, especially 
      ;; if you don't need to make the function look like a function
      ;; defined via a top-level defun.
      (setf (fdefinition func-name) (compile nil lambda-form)))))

(defun add-func-to-arr (name)
  ;; Do whatever you want to do...
  )

More background on the uses of this mechanism might help elicit more
detailed and/or apropriate advice...

Regs, Pierre.

-- 
Pierre Mai <····@acm.org>         PGP and GPG keys at your nearest Keyserver
  "One smaller motivation which, in part, stems from altruism is Microsoft-
   bashing." [Microsoft memo, see http://www.opensource.org/halloween1.html]