From: Jonathan
Subject: Returning a lisp function from a text file.
Date: 
Message-ID: <3nAWOYXYULO3IFL2tpRrn2rmXwzJ@4ax.com>
Hi,

I am rewriting a routine that I wrote when I was first learning lisp
and would like to know what is the best way to rewrite it. Basically,
I have a set of macros that read an ascii file filled with lisp code
and return the result in a function. This looks something like:

user: (make-func-from-file function-to-make-name file-name)
user: (describe #'function-to-make-name)
#<Interpreted Function FUNCTION-TO-MAKE-NAME> is a FUNCTION.
  The arguments are (REQ)

This is a poor design choice initially for several reasons particular
to my application. One particular thing is that it would be better if
a function was returned instead of passing a name of a function to
define as occasionally it is inconvenient to create a function when it
will only be used once. I have tried to rewrite my macro as a
function, but have run into problems and am wondering if this is a
situation where a macro is the only solution. Does anyone have any
suggestions on how to rewrite this so that something similar to:

user: (setf (symbol-function my-func) (func-from-file file-name))

will work?

Thanks,
Jonathan

From: Pierre R. Mai
Subject: Re: Returning a lisp function from a text file.
Date: 
Message-ID: <87zoq1v35m.fsf@orion.dent.isdn.cs.tu-berlin.de>
Jonathan <···@scorekeep.com> writes:

> I am rewriting a routine that I wrote when I was first learning lisp
> and would like to know what is the best way to rewrite it. Basically,
> I have a set of macros that read an ascii file filled with lisp code
> and return the result in a function. This looks something like:
> 
> user: (make-func-from-file function-to-make-name file-name)
> user: (describe #'function-to-make-name)
> #<Interpreted Function FUNCTION-TO-MAKE-NAME> is a FUNCTION.
>   The arguments are (REQ)
> 
> This is a poor design choice initially for several reasons particular
> to my application. One particular thing is that it would be better if
> a function was returned instead of passing a name of a function to
> define as occasionally it is inconvenient to create a function when it
> will only be used once. I have tried to rewrite my macro as a
> function, but have run into problems and am wondering if this is a
> situation where a macro is the only solution. Does anyone have any
> suggestions on how to rewrite this so that something similar to:
> 
> user: (setf (symbol-function my-func) (func-from-file file-name))
> 
> will work?

Assuming that you have mechanisms in place to get the lisp code for
the body and the lambda-list to use on the function (which should be
trivial, but they will depend on the format of your files), the
following should work out of the box:

(defun func-from-file (file-name)
  (with-open-file (stream file-name)
    (let ((lambda-list (read-lambda-list stream))
          (body (read-body stream)))
      (coerce `(lambda ,lambda-list ,@body) 'function))))

This will usually yield an interpreted function on most
implementations which have an interpreter.  To get a compiled
function, use the following:

(defun func-from-file (file-name)
  (with-open-file (stream file-name)
    (let ((lambda-list (read-lambda-list stream))
          (body (read-body stream)))
      (compile nil `(lambda ,lambda-list ,@body)))))

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]
From: Jonathan
Subject: Re: Returning a lisp function from a text file.
Date: 
Message-ID: <l9kXOXb8heGbS5CSHtrw9I6W9Ip3@4ax.com>
Pierre,

Thank you so much for the help. I now have integrated your suggestion
into my routines. I have now come upon a new problem, namely that I
want to pass the function I receive back from func-from-file to a
macro, but cannot do this without creating an interned symbol for the
function first. What I would like to do is:

(let ((my-func (func-from-file "a-file-with-list-contents")))
  (publish :func (some-with-macros my-func)))

But I get the error:

error Illegal function object: PACKAGE-I-WAS-IN::TEMP-FUNC.

when the publish call runs.

I can get around this by doing:

(setf (symbol-function 'me) 
        (func-from-file "a-file-with-list-contents"))
(publish :func (some-with-macros me))

Which is actually what I asked to be able to do in my original
message, but not what I would like to ideally do. The whole crux of
this rewrite was to allow a let of this type to keep from having to
create a non-local variable to hold the function (basically, if the
entity that grabs the function when passed to publish ever
relinquishes its reference to the function, I would like the gc to be
able to prune the function out of memory). I suppose I could simply
unintern the me variable in the above working example after I publish
the function, but it would be much cleaner if I could just never
create the non-local variable in the first place.

Any suggestions you have will be appreciated and thanks again for the
great response.

-Jonathan




On 08 May 2000 10:48:05 +0200, ····@acm.org (Pierre R. Mai) wrote:

>Jonathan <···@scorekeep.com> writes:
>
>> I am rewriting a routine that I wrote when I was first learning lisp
>> and would like to know what is the best way to rewrite it. Basically,
>> I have a set of macros that read an ascii file filled with lisp code
>> and return the result in a function. This looks something like:
>> 
>> user: (make-func-from-file function-to-make-name file-name)
>> user: (describe #'function-to-make-name)
>> #<Interpreted Function FUNCTION-TO-MAKE-NAME> is a FUNCTION.
>>   The arguments are (REQ)
>> 
>> This is a poor design choice initially for several reasons particular
>> to my application. One particular thing is that it would be better if
>> a function was returned instead of passing a name of a function to
>> define as occasionally it is inconvenient to create a function when it
>> will only be used once. I have tried to rewrite my macro as a
>> function, but have run into problems and am wondering if this is a
>> situation where a macro is the only solution. Does anyone have any
>> suggestions on how to rewrite this so that something similar to:
>> 
>> user: (setf (symbol-function my-func) (func-from-file file-name))
>> 
>> will work?
>
>Assuming that you have mechanisms in place to get the lisp code for
>the body and the lambda-list to use on the function (which should be
>trivial, but they will depend on the format of your files), the
>following should work out of the box:
>
>(defun func-from-file (file-name)
>  (with-open-file (stream file-name)
>    (let ((lambda-list (read-lambda-list stream))
>          (body (read-body stream)))
>      (coerce `(lambda ,lambda-list ,@body) 'function))))
>
>This will usually yield an interpreted function on most
>implementations which have an interpreter.  To get a compiled
>function, use the following:
>
>(defun func-from-file (file-name)
>  (with-open-file (stream file-name)
>    (let ((lambda-list (read-lambda-list stream))
>          (body (read-body stream)))
>      (compile nil `(lambda ,lambda-list ,@body)))))
>
>Regs, Pierre.
From: Barry Margolin
Subject: Re: Returning a lisp function from a text file.
Date: 
Message-ID: <anWR4.6$pj4.626@burlma1-snr2>
In article <····························@4ax.com>,
Jonathan  <···@scorekeep.com> wrote:
>Thank you so much for the help. I now have integrated your suggestion
>into my routines. I have now come upon a new problem, namely that I
>want to pass the function I receive back from func-from-file to a
>macro, but cannot do this without creating an interned symbol for the
>function first. What I would like to do is:

>
>(let ((my-func (func-from-file "a-file-with-list-contents")))
>  (publish :func (some-with-macros my-func)))

You can't do this, because macros don't evaluate their arguments.  They're
expanded at compile time, but FUNC-FROM-FILE won't be called until runtime.

>But I get the error:
>
>error Illegal function object: PACKAGE-I-WAS-IN::TEMP-FUNC.
>
>when the publish call runs.
>
>I can get around this by doing:
>
>(setf (symbol-function 'me) 
>        (func-from-file "a-file-with-list-contents"))
>(publish :func (some-with-macros me))
>
>Which is actually what I asked to be able to do in my original
>message, but not what I would like to ideally do. The whole crux of
>this rewrite was to allow a let of this type to keep from having to
>create a non-local variable to hold the function (basically, if the
>entity that grabs the function when passed to publish ever
>relinquishes its reference to the function, I would like the gc to be
>able to prune the function out of memory). I suppose I could simply
>unintern the me variable in the above working example after I publish
>the function, but it would be much cleaner if I could just never
>create the non-local variable in the first place.

What is SOME-WITH-MACROS doing that requires it to be a macro in the first
place?

-- 
Barry Margolin, ······@genuity.net
Genuity, 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: Tim Moore
Subject: Re: Returning a lisp function from a text file.
Date: 
Message-ID: <8f9cek$e9d$0@216.39.145.192>
On Tue, 9 May 2000, Jonathan wrote:

> Pierre,
> 
> Thank you so much for the help. I now have integrated your suggestion
> into my routines. I have now come upon a new problem, namely that I
> want to pass the function I receive back from func-from-file to a
> macro, but cannot do this without creating an interned symbol for the
> function first. What I would like to do is:
> 
> (let ((my-func (func-from-file "a-file-with-list-contents")))
>   (publish :func (some-with-macros my-func)))
> 
> But I get the error:
> 
> error Illegal function object: PACKAGE-I-WAS-IN::TEMP-FUNC.
> 
> when the publish call runs.

This is a problem in some-with-macros.  In your macroexpansion you want to
be using funcall instead of putting temp-func in the functional position.
I.e., (funcall temp-func ...) instead of (temp-func ...)

Tim