From: Barry Margolin
Subject: Re: Are Anonymous Functions Garbage Collected?
Date: 
Message-ID: <barmar-3A38C9.00195013102004@comcast.dca.giganews.com>
In article <··············@david-steuber.com>,
 David Steuber <·····@david-steuber.com> wrote:

> I have more than one question here actually.  I have a function called
> make-chance-table which I first tried to do as a macro but screwed up
> somewhere.  I decided I could do it as a function, but it uses compile
> in it which must be nearly as bad as using eval.  While it is not a
> requirement, it would be nice to be able to write this thing as a
> macro.  make-chance-table is supposed to build a plist like data
> structure consisting of integers and functions:
> 
> (defun make-chance-table (table)
>   (let ((tbl nil))
>     (labels ((mct (ct)
>                (when ct
>                  (push (car ct) tbl)
>                  (push (compile nil (cadr ct)) tbl)
>                  (mct (cddr ct)))))
>       (mct table))
>     (nreverse tbl)))
> 
> (defvar *a-chance-table*
>   '(1 (lambda () 'red)
>     2 (lambda () 'orange)
>     3 (lambda () 'yellow)
>     4 (lambda () 'green)
>     5 (lambda () 'blue)
>     6 (lambda () 'indigo)
>     7 (lambda () 'violet)
>     8 (lambda () 'foo)))

Why do you need a function or macro at all?  You can just write:

(defvar *a-chance-table*
  `(1 ,(lambda () 'red)
    2 ,(lambda () 'orange)
    ...))

> 
> CL-USER> (make-chance-table *a-chance-table*)
> (1 #<Anonymous Function #x654B916> 2 #<Anonymous Function #x654B07E> 3
> #<Anonymous Function #x654A7E6> 4 #<Anonymous Function #x6549F4E> 5
> #<Anonymous Function #x65496B6> 6 #<Anonymous Function #x6548E1E> 7
> #<Anonymous Function #x6548586> 8 #<Anonymous Function #x6547D3E>)
> 
> Other requirements I have are to preserve the order of the list and to
> allow for function names in place of the lambda forms.  I think I can
> handle the last using an if form.

For function names you can use ,#'name where the above example has 
,(lambda ...).

> 
> A yet to be defined function will funcall the functions.
> 
> So is using compile as eval as I think it is?  How do I make a macro
> out of make-chance-table?  Can these functions get garbage collected
> at some point as I have the code now?

If you don't like writing all those commas, you can do:

(defmacro define-chance-table (var &rest ct-entries)
  `(defvar ,var 
           (list ,@(loop for (key func) on ct-entries by #'cddr
                         collect `',key
                         collect `#',func))))

(define-chance-table *a-chance-table*
  1 (lambda () 'red)
  2 (lambda () 'orange)
  3 func-name
  ...)

As far as garbage collection goes -- the functions will be GCed when 
there are no references to them.  As long as they're in the list and the 
variable is bound to the list, they won't become garbage.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***

From: Albert Reiner
Subject: Re: Are Anonymous Functions Garbage Collected?
Date: 
Message-ID: <vw8y8ibrm9m.fsf@berry.phys.ntnu.no>
[Barry Margolin <······@alum.mit.edu>, Wed, 13 Oct 2004 00:19:50 -0400]:
> In article <··············@david-steuber.com>,
>  David Steuber <·····@david-steuber.com> wrote:
> > (defun make-chance-table (table)
> >   (let ((tbl nil))
> >     (labels ((mct (ct)
> >                (when ct
> >                  (push (car ct) tbl)
> >                  (push (compile nil (cadr ct)) tbl)
                            ^^^^^^^
-------------------------------'
> >                  (mct (cddr ct)))))
> >       (mct table))
> >     (nreverse tbl)))
> 
> Why do you need a function or macro at all?  You can just write:
> 
> (defvar *a-chance-table*
>   `(1 ,(lambda () 'red)
>     2 ,(lambda () 'orange)
>     ...))

But that does not compile the functions.

Albert.
From: Peder O. Klingenberg
Subject: Re: Are Anonymous Functions Garbage Collected?
Date: 
Message-ID: <ks7jpv54kp.fsf@beto.netfonds.no>
Albert Reiner <·······@tph.tuwien.ac.at> writes:

> But that does not compile the functions.

It does if you compile the defvar form.  At least in Lispworks.

...Peder...
-- 
I wish a new life awaited _me_ in some off-world colony.
From: David Steuber
Subject: Re: Are Anonymous Functions Garbage Collected?
Date: 
Message-ID: <4ddd570c.0410131410.3ab66b0e@posting.google.com>
·····@news.klingenberg.no (Peder O. Klingenberg) wrote in message news:<··············@beto.netfonds.no>...
> Albert Reiner <·······@tph.tuwien.ac.at> writes:
> 
> > But that does not compile the functions.
> 
> It does if you compile the defvar form.  At least in Lispworks.

I thought OpenMCL wasn't compiling the lambda forms.  That wasn't the
problem though.  defvar doesn't bind to a bound variable whereas
defparameter does.  Oops.  It's specified that way in the CLHS.
From: Pascal Bourguignon
Subject: Re: Are Anonymous Functions Garbage Collected?
Date: 
Message-ID: <87hdoypb6i.fsf@thalassa.informatimago.com>
·····@david-steuber.com (David Steuber) writes:

> ·····@news.klingenberg.no (Peder O. Klingenberg) wrote in message news:<··············@beto.netfonds.no>...
> > Albert Reiner <·······@tph.tuwien.ac.at> writes:
> > 
> > > But that does not compile the functions.
> > 
> > It does if you compile the defvar form.  At least in Lispworks.
> 
> Apparantly OpenMCL does not compile the functions :-(
> 
> I thought the comma ment to evaluate the bit after it in a backquoted expression.

You can force it.

(mapcar (lambda (x) (if (atomp x) x (compile nil x)))
    (list 1 (lambda () ...)
          2 (lambda () ...)
          ...))

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

Voting Democrat or Republican is like choosing a cabin in the Titanic.
From: David Steuber
Subject: Re: Are Anonymous Functions Garbage Collected?
Date: 
Message-ID: <87mzypw08w.fsf@david-steuber.com>
···@conquest.OCF.Berkeley.EDU (Thomas F. Burdick) writes:

> ·····@david-steuber.com (David Steuber) writes:
> 
> > ·····@news.klingenberg.no (Peder O. Klingenberg) wrote in message news:<··············@beto.netfonds.no>...
> > > Albert Reiner <·······@tph.tuwien.ac.at> writes:
> > > 
> > > > But that does not compile the functions.
> > > 
> > > It does if you compile the defvar form.  At least in Lispworks.
> > 
> > Apparantly OpenMCL does not compile the functions :-(
> 
> Actually, OpenMCL compiles everything, it doesn't have an interpreter.
> If you're ever curious or doubtful, try using disassemble:
> 
>   (defvar *foo*
>     (list 1 (lambda () 1)
>           2 (lambda () 2)))
> 
>   (disassemble (second *foo*))

Right.  It was a case of trying to debug the wrong propblem.  I forgot
that DEFVAR does not rebind a variable so I was stuck with the old
value each time.
-- 
An ideal world is left as an excercise to the reader.
   --- Paul Graham, On Lisp 8.1
From: Lisptracker
Subject: Re: Are Anonymous Functions Garbage Collected?
Date: 
Message-ID: <c23ae4f8.0410150150.2abd0ff6@posting.google.com>
·····@news.klingenberg.no (Peder O. Klingenberg) wrote in message news:<··············@beto.netfonds.no>...
> Albert Reiner <·······@tph.tuwien.ac.at> writes:
> 
> > But that does not compile the functions.
> 
> It does if you compile the defvar form.  At least in Lispworks.
> 
> ...Peder...

I've tried to do everything like:

(defvar *funs* (list 1 #'(lambda (x) (1+ x))))

than compiled this region, but always got INTERPRETED-FUNCTION

IMHO better use:

(defmacro clambda (args &rest forms)
  `(compile nil '(lambda (,@args) ,@forms)))

(defvar *funs* `(1 ,(clambda () 'orange)))

Lisptracker ···········@mail.ru
From: Barry Margolin
Subject: Re: Are Anonymous Functions Garbage Collected?
Date: 
Message-ID: <barmar-0620AA.22044815102004@comcast.dca.giganews.com>
In article <····························@posting.google.com>,
 ···········@mail.ru (Lisptracker) wrote:

> ·····@news.klingenberg.no (Peder O. Klingenberg) wrote in message 
> news:<··············@beto.netfonds.no>...
> > Albert Reiner <·······@tph.tuwien.ac.at> writes:
> > 
> > > But that does not compile the functions.
> > 
> > It does if you compile the defvar form.  At least in Lispworks.
> > 
> > ...Peder...
> 
> I've tried to do everything like:
> 
> (defvar *funs* (list 1 #'(lambda (x) (1+ x))))
> 
> than compiled this region, but always got INTERPRETED-FUNCTION

Did you compile the file that contained that line?

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
From: Lisptracker
Subject: Re: Are Anonymous Functions Garbage Collected?
Date: 
Message-ID: <c23ae4f8.0410171008.7c6cd1dc@posting.google.com>
Barry Margolin <······@alum.mit.edu> wrote in message news:<····························@comcast.dca.giganews.com>...
> In article <····························@posting.google.com>,
>  ···········@mail.ru (Lisptracker) wrote:
> 
> > ·····@news.klingenberg.no (Peder O. Klingenberg) wrote in message 
> > news:<··············@beto.netfonds.no>...
> > > Albert Reiner <·······@tph.tuwien.ac.at> writes:
> > > 
> > > > But that does not compile the functions.
> > > 
> > > It does if you compile the defvar form.  At least in Lispworks.
> > > 
> > > ...Peder...
> > 
> > I've tried to do everything like:
> > 
> > (defvar *funs* (list 1 #'(lambda (x) (1+ x))))
> > 
> > than compiled this region, but always got INTERPRETED-FUNCTION
> 
> Did you compile the file that contained that line?

Sorry, simply I was trapped by DEFVAR form. Those functions remained
uncompiled because of incremental evaluation of DEFVAR form. If you
have evaluated defvar form, following incremental compilation will not
change that form.

So LispWorks in fact COMPILE anonymous functions in expressions like
(list 1 #'(lambda (x) (1+ x))).



Lisptracker.
From: David Steuber
Subject: Re: Are Anonymous Functions Garbage Collected?
Date: 
Message-ID: <87wtxuv0ir.fsf@david-steuber.com>
Barry Margolin <······@alum.mit.edu> writes:

> Why do you need a function or macro at all?  You can just write:
> 
> (defvar *a-chance-table*
>   `(1 ,(lambda () 'red)
>     2 ,(lambda () 'orange)
>     ...))

D'oh!  This is just me making things more complicated than they need
to be.  I was just thinking I didn't want 1 to be evaluated as a
function call.

> For function names you can use ,#'name where the above example has 
> ,(lambda ...).

Works for me.

> If you don't like writing all those commas, you can do:
> 
> (defmacro define-chance-table (var &rest ct-entries)
>   `(defvar ,var 
>            (list ,@(loop for (key func) on ct-entries by #'cddr
>                          collect `',key
>                          collect `#',func))))
> 
> (define-chance-table *a-chance-table*
>   1 (lambda () 'red)
>   2 (lambda () 'orange)
>   3 func-name
>   ...)

Nice use of loop there.  I only thought of recursion to traverse a
list by cddr.

> As far as garbage collection goes -- the functions will be GCed when 
> there are no references to them.  As long as they're in the list and the 
> variable is bound to the list, they won't become garbage.

Ok.  I was hoping that code followed the normal garbage collection
rules but I wasn't sure.

Thanks.

-- 
An ideal world is left as an excercise to the reader.
   --- Paul Graham, On Lisp 8.1
From: Peter Seibel
Subject: Re: Are Anonymous Functions Garbage Collected?
Date: 
Message-ID: <m3u0sxki9u.fsf@javamonkey.com>
"Steven M. Haflich" <·················@alum.mit.edu> writes:

> Barry Margolin wrote:
>
>> (defvar *a-chance-table*
>>   `(1 ,(lambda () 'red)
>>     2 ,(lambda () 'orange)
>>     ...))
>
> This may work in uncompiled files, but is not portable Common Lisp
> if the file containing thjis form is file compiled. Check ANS
> 3.2.4.2.2 which makes the plain statement "Functions are not
> externalizable objects." They may be externalizable (at least for
> null closures) in every important implementation, but that doesn't
> make them portable ANSI CL.

How do you know when an object needs to be externalizable? Let's
assume the backquote expression was replaced with this:

  (defvar *a-chance-table*
    (list 1 (lambda () 'red)
          2 (lambda () 'orange)))

Is that still not portable. (I assume it's not since that's just an
equivalent way of writing the backquoted expression.) How about this:

  (defun make-chance-table ()
    (list 1 (lambda () 'red) 2 (lambda () 'orange)))

  (defvar *a-chance-table* (make-chance-table))

I would think make-chance-table can be (portably) compiled because
that's just a regular use of closures. And then I'd assume I can use
it to compute the value of a variable. But maybe I'm wrong about one
of those assumptions? And if it can, is there a way to explain the
difference between using an expression in a function and using the
same expression to compute the value of a variable?

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: Timothy Moore
Subject: Re: Are Anonymous Functions Garbage Collected?
Date: 
Message-ID: <wdroej5znko.fsf@serveur5.labri.fr>
Peter Seibel <·····@javamonkey.com> writes:
> "Steven M. Haflich" <·················@alum.mit.edu> writes:
> 
> > Barry Margolin wrote:
> >
> >> (defvar *a-chance-table*
> >>   `(1 ,(lambda () 'red)
> >>     2 ,(lambda () 'orange)
> >>     ...))
> >
> > This may work in uncompiled files, but is not portable Common Lisp
> > if the file containing thjis form is file compiled. Check ANS
> > 3.2.4.2.2 which makes the plain statement "Functions are not
> > externalizable objects." They may be externalizable (at least for

That isn't right. , expressions in backquote aren't evaluated at read
time. Backquote expands into program structure that returns the
desired result.

> > null closures) in every important implementation, but that doesn't
> > make them portable ANSI CL.
> 
> How do you know when an object needs to be externalizable? Let's
> assume the backquote expression was replaced with this:
> 
>   (defvar *a-chance-table*
>     (list 1 (lambda () 'red)
>           2 (lambda () 'orange)))
> 
> Is that still not portable. (I assume it's not since that's just an
> equivalent way of writing the backquoted expression.) How about this:

Yes, that is portable, just like Barry's expression above. If you
replaced ,(lambda ...) with #.(lambda () ...), then the
"externalizable objects" issue comes into play.

Tim
From: Peter Seibel
Subject: Re: Are Anonymous Functions Garbage Collected?
Date: 
Message-ID: <m3hdowinyb.fsf@javamonkey.com>
Vassil Nikolov <········@poboxes.com> writes:

> Peter Seibel <·····@javamonkey.com> writes:
>
>> [...]
>> And if it can, is there a way to explain the
>> difference between using an expression in a function and using the
>> same expression to compute the value of a variable?
>
>   If this is about externalization, the difference is between the
>   reader returning an expression vs. the reader returning the value of
>   that expression, in the case when that value is not externalizable
>   (e.g between (... #'(LAMBDA ...) ...) and  (... #.#'(LAMBDA ...) ...).

Right, which was why I was confused by Steven's post; the form he said
was non-portable included only #'(lambda ...) not #.#'(lambda ...) as
far as I could tell.

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: Vassil Nikolov
Subject: Re: Are Anonymous Functions Garbage Collected?
Date: 
Message-ID: <lzd5zg21x9.fsf@janus.vassil.nikolov.names>
Peter Seibel <·····@javamonkey.com> writes:

> Vassil Nikolov <········@poboxes.com> writes:
>
>> [...]
>>   If this is about externalization, the difference is between the
>>   reader returning an expression vs. the reader returning the value of
>>   that expression, in the case when that value is not externalizable
>>   (e.g between (... #'(LAMBDA ...) ...) and  (... #.#'(LAMBDA ...) ...).
>
> Right, which was why I was confused by Steven's post; the form he said
> was non-portable included only #'(lambda ...) not #.#'(lambda ...) as
> far as I could tell.

  Oh, and there is another (bigger) problem with #.#'(LAMBDA ...) in
  the general case: it loses the lexical environment.

  ---Vassil.

-- 
Vassil Nikolov <········@poboxes.com>

Hollerith's Law of Docstrings: Everything can be summarized in 72 bytes.