Lisp HUG Maillist Archive

Funcallable Standard Objects?

I have been experimenting on/off with Funcallable-Standard-Class metaclass and the resulting Funcallable-Standard-Objects. 

I notice a peculiar asymmetry, wherein you must assign the functional behavior in an Initialize-Instance method using CLOS:SET-FUNCALLABLE-INSTANCE-FUNCTION, yet there is no corresponding method to retrieve the functional behavior of the instance once constructed.

Does anyone know or understand the reasoning behind this asymmetry. It has the feel of an intentional decision, but I’m puzzled about the language theoretic reasons behind it.

In order to retain visibility of the function, I have resorted to making an instance slot to hold the function, then using an indirect dispatch function in the initialize-instance method:

(defclass standard-handler ()
  ((handler-fn  :accessor handler-fn  :initarg :fn))
  (:metaclass clos:funcallable-standard-class))

;; -----------------------------------------

(defmethod initialize-instance :after ((h standard-handler) &key &allow-other-keys)
  (clos:set-funcallable-instance-function h (lambda (&rest args)
                                              (apply (handler-fn h) args))))


- DM

Re: Funcallable Standard Objects?

Why does this matter to me? Having access to the function performed by the instance allows one to wrap the function without changing all references to it. The instance object becomes a ref-cell. Without access to the function it becomes impossible to generically alter the behavior of the function.

- DM


On Apr 1, 2017, at 03:05, David McClain <dbm@refined-audiometrics.com> wrote:

I have been experimenting on/off with Funcallable-Standard-Class metaclass and the resulting Funcallable-Standard-Objects. 

I notice a peculiar asymmetry, wherein you must assign the functional behavior in an Initialize-Instance method using CLOS:SET-FUNCALLABLE-INSTANCE-FUNCTION, yet there is no corresponding method to retrieve the functional behavior of the instance once constructed.

Does anyone know or understand the reasoning behind this asymmetry. It has the feel of an intentional decision, but I’m puzzled about the language theoretic reasons behind it.

In order to retain visibility of the function, I have resorted to making an instance slot to hold the function, then using an indirect dispatch function in the initialize-instance method:

(defclass standard-handler ()
  ((handler-fn  :accessor handler-fn  :initarg :fn))
  (:metaclass clos:funcallable-standard-class))

;; -----------------------------------------

(defmethod initialize-instance :after ((h standard-handler) &key &allow-other-keys)
  (clos:set-funcallable-instance-function h (lambda (&rest args)
                                              (apply (handler-fn h) args))))


- DM

Re: Funcallable Standard Objects?

Hi,

I recall reading a late version of the CLOS MOP specification before it was published in AMOP, where the funcallable instance function wasn’t even a function, but some more low-level entity that you couldn’t use like a regular function. My guess is that allowing the function not to be retrieved anymore allows for some low-level optimizations, at least in some architectures of that time (but that’s just me speculating).

Pascal

On 1 Apr 2017, at 12:05, David McClain <dbm@refined-audiometrics.com> wrote:

I have been experimenting on/off with Funcallable-Standard-Class metaclass and the resulting Funcallable-Standard-Objects. 

I notice a peculiar asymmetry, wherein you must assign the functional behavior in an Initialize-Instance method using CLOS:SET-FUNCALLABLE-INSTANCE-FUNCTION, yet there is no corresponding method to retrieve the functional behavior of the instance once constructed.

Does anyone know or understand the reasoning behind this asymmetry. It has the feel of an intentional decision, but I’m puzzled about the language theoretic reasons behind it.

In order to retain visibility of the function, I have resorted to making an instance slot to hold the function, then using an indirect dispatch function in the initialize-instance method:

(defclass standard-handler ()
  ((handler-fn  :accessor handler-fn  :initarg :fn))
  (:metaclass clos:funcallable-standard-class))

;; -----------------------------------------

(defmethod initialize-instance :after ((h standard-handler) &key &allow-other-keys)
  (clos:set-funcallable-instance-function h (lambda (&rest args)
                                              (apply (handler-fn h) args))))


- DM

--
Pascal Costanza


Re: Funcallable Standard Objects?

I suspect the reason might be that, although the obvious implementation is to use a trampoline which calls into the function, implementations might not want to do that and instead might want to pull apart the function and essentially make the instance *be* a mutant version of it.  For the original function to be recoverable would then require it to be stashed somewhere in a slot, and perhaps they did not want to impose that overhead on implementations which had gone to the effort of not using a trampoline.

That's just a guess though: probably the only way of knowing would be to ask someone who was involved in the MOP specification.

On 1 Apr 2017, at 11:05, David McClain <dbm@refined-audiometrics.com> wrote:

I have been experimenting on/off with Funcallable-Standard-Class metaclass and the resulting Funcallable-Standard-Objects. 

I notice a peculiar asymmetry, wherein you must assign the functional behavior in an Initialize-Instance method using CLOS:SET-FUNCALLABLE-INSTANCE-FUNCTION, yet there is no corresponding method to retrieve the functional behavior of the instance once constructed.

Does anyone know or understand the reasoning behind this asymmetry. It has the feel of an intentional decision, but I’m puzzled about the language theoretic reasons behind it.

In order to retain visibility of the function, I have resorted to making an instance slot to hold the function, then using an indirect dispatch function in the initialize-instance method:

(defclass standard-handler ()
  ((handler-fn  :accessor handler-fn  :initarg :fn))
  (:metaclass clos:funcallable-standard-class))

;; -----------------------------------------

(defmethod initialize-instance :after ((h standard-handler) &key &allow-other-keys)
  (clos:set-funcallable-instance-function h (lambda (&rest args)
                                              (apply (handler-fn h) args))))


- DM

Updated at: 2020-12-10 08:31 UTC