From: Len Charest
Subject: Whither EVAL?
Date: 
Message-ID: <1993Feb10.014946.5322@jpl-devvax.jpl.nasa.gov>
I'm trying to define a closure generator where the single argument to the
generator is a Lisp code fragment that is to be evaluated by the closure. The
argument to the generator must be evaluated (i.e., the generator must be a
function. So far I have

(defun make-setter (code)
  (let ((v nil))
    (eval `(function (lambda ()
                       (print v)
                       (setq v ,code))))))

Test:
> (setq f (make-setter '(random 10)))
#<Interpreted-function ...>
> (funcall f)
nil
9
> (funcall f)
9
3

Is there any way I can get rid of the EVAL in the above and retain the same
functionality? Since the CODE is a source code fragment I want to build the
lambda form dynamically. But FUNCTION is a special form that does not eval its
argument, hence the appearance of EVAL. 

..................................................
                                  Len Charest, Jr.
                 JPL Artificial Intelligence Group
                          ·······@aig.jpl.nasa.gov

From: david kuznick
Subject: Re: Whither EVAL?
Date: 
Message-ID: <1993Feb10.084216.5341@titan.ksc.nasa.gov>
I think what you really want here is a MACRO.

(Ignoring the variable capture issues. We really should be GENSYMing a
local variable instead of using v):

(defmacro make-setter (code)
  `(let ((v nil))
      #'(lambda ()
           (print v)
           (setq v ,code))))))

With the GENSYMing:

(defmacro make-setter (code)
   (let ((var (gensym))
    `(let ((,var nil))
       #'(lambda ()
           (print ,var)
           (setq ,var ,code))))))

Now just say (setf f (make-setter (random 10)))
and away you go.

The only CAVEAT I have is that I have seen Lisps (Lucid for example) have
problems with macros that generated closures.
--
**
David Kuznick
·······@meglos.mdcorp.ksc.nasa.gov
MUTLEY! Do something!  - D.D.
From: Scott McKay
Subject: Re: Whither EVAL?
Date: 
Message-ID: <19930210154307.3.SWM@SUMMER.SCRC.Symbolics.COM>
    Date: Wed, 10 Feb 1993 08:42 EST
    From: david kuznick <·······@meglos.mdcorp.ksc.nasa.gov>


    I think what you really want here is a MACRO.

    (Ignoring the variable capture issues. We really should be GENSYMing a
    local variable instead of using v):

    (defmacro make-setter (code)
      `(let ((v nil))
	  #'(lambda ()
	       (print v)
	       (setq v ,code))))))

    With the GENSYMing:

    (defmacro make-setter (code)
       (let ((var (gensym))
	`(let ((,var nil))
	   #'(lambda ()
	       (print ,var)
	       (setq ,var ,code))))))

    Now just say (setf f (make-setter (random 10)))
    and away you go.

    The only CAVEAT I have is that I have seen Lisps (Lucid for example) have
    problems with macros that generated closures.

CLIM does this kind of stuff all the time, and it works properly under
the Lucid, Franz, Harlequin, MCL, and Symbolics Lisp implementations.
From: david kuznick
Subject: Whither EVAL?
Date: 
Message-ID: <9302101552.AA04991@meglos.mdcorp.ksc.nasa.gov>
   Date: Wed, 10 Feb 1993 10:43-0500
   From: Scott McKay <···@STONY-BROOK.SCRC.Symbolics.COM>

       Date: Wed, 10 Feb 1993 08:42 EST
       From: david kuznick <·······@meglos.mdcorp.ksc.nasa.gov>


       I think what you really want here is a MACRO.

       (Ignoring the variable capture issues. We really should be GENSYMing a
       local variable instead of using v):

       (defmacro make-setter (code)
	 `(let ((v nil))
	     #'(lambda ()
		  (print v)
		  (setq v ,code))))))

       With the GENSYMing:

       (defmacro make-setter (code)
	  (let ((var (gensym))
	   `(let ((,var nil))
	      #'(lambda ()
		  (print ,var)
		  (setq ,var ,code))))))

       Now just say (setf f (make-setter (random 10)))
       and away you go.

       The only CAVEAT I have is that I have seen Lisps (Lucid for example) have
       problems with macros that generated closures.

   CLIM does this kind of stuff all the time, and it works properly under
   the Lucid, Franz, Harlequin, MCL, and Symbolics Lisp implementations.


In a pre-4.1 (probably 4.0) version of Lucid Lisp I have personally
seen macro-generating closures compiled with (speed 3) (safety 0) have
the compiler generate garbage in the place of the closure that would
move around during GCs causing the dubuger to be entered at
different times.  Unfortunately that was 1 job and at least 2
years ago so I don't have the exact code.  Actually I do remember the
macro generated the closure directly; not within a LET.

**
David Kuznick
·······@meglos.mdcorp.ksc.nasa.gov
MUTLEY! Do something!  - D.D.