[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Lexical environment of method



>From att!whutt.att.com!davel Sat Mar 10 15:35 EST 1990
>>From att!AI-SUN.jpl.nasa.gov!Charest Fri Mar  9 14:59 PST 1990
>>
>>I want to write an arbitrary function to be called inside the body of a method and I want the function to receive the
>>lexical environment of the method. The function is to be compiled and stored on an instance variable of a flavor. The
>>method will take an arbitrary arglist and simply forward it to the function. For example: 
>>
>>(defflavor widget ((fn) (ivar "puzzle")) ())
>>>>
>>(setq foo (make-instance 'widget :fn (compile nil '(lambda (string) (format t "~%~a ~a" string ivar)))))
>>;;;see what is stored on fn
>>(widget-fn foo) => #<dtp-compiled-function ...>
>>
>>(defmethod (doit widget) (&optional &rest args)
>>  ;;fn knows about the lexical environment of this method
>>  (apply fn args))
>>
>>;;;call the doit method
>>(doit foo "Jigsaw") =>
>>Jigsaw puzzle

>Try this:
>(defflavor widget ((fn) (ivar "puzzle")) () :writable-instance-variables)
>(setq foo (make-instance 'widget))
>(setf (widget-fn foo) (compile nil #'(lambda (string) (format nil 
>     "~a ~a" string (widget-ivar foo)))

Silly me.  Can't compile closures; the above will only work if
foo is a special variable.  Try instead:
(SETF foo (make-instance 'widget))
(LET ((x (GENSYM)))
  (SET x foo)  
  (SETF (widget-fn foo) 
        (compile nil `(lambda (string) 
                         (declare (special ,x))
                         (format nil "~a ~a"
                                 string (widget-ivar ,x))))))
or
(LET* ((foo (make-instance 'widget)))
       (fn (compile nil 
                    '(LAMBDA (foo string)
                         (FORMAT NIL "~A ~A" string (widget-ivar foo))))))
  (SETF (widget-fn foo)
        #'(LAMBDA (string) 
       	    (FUNCALL fn foo string))))

If you wanted to get fancy, you could even create a macro to translate
(widget-lambda (string) forms...)
into 
(LET ((#:f1 (compile ()
           (lambda (foo string) (let ((ivar (widget-ivar foo))) forms...))
  #'(lambda (string) (funcall #:f1 foo string)))

   
>>The motivation for the above is to essentially have methods that are private to a specific instance rather than available to
>>an entire flavor (class).
...	
>		Thanx,
>		Len Charest, JPL AI Lab
	
These opinions are shareware.  If you like the product,
please send your $0.02 to
               David Loewenstern
   {backbone!}att!whutt!davel which is davel@whutt.att.com

P.S.: We're having mail problems, Len, so I'd appreciate it
if you'd send back an acknowledgement even if you don't find this
helpful.