From: Peter Seibel
Subject: Which do you like better?
Date: 
Message-ID: <m3k6ua6vlz.fsf@javamonkey.com>
Suppose as part of some macrology I need a function (to be executed at
macroexpansion time) that takes a symbol and returns a function that
converts a value to the "type" named by the symbol. "Type" is in
quotes because it's not necessarily a Lisp type--just a symbol. The
mapping will be defined via a macro define-type-conversion. Here are
two ways to implement that macro. Anyone have any strong feelings
and/or arguments that one is better than the other?

  (defmacro define-type-conversion (name (value) &body body)
    `(eval-when (:compile-toplevel :load-toplevel :execute)
       (setf (get ',name 'conversion-function)
             #'(lambda (,value) ,@body))))

  (defmacro define-type-conversion (name (value) &body body)
    (with-gensyms (typevar)
      `(eval-when (:compile-toplevel :load-toplevel :execute)
         (defmethod conversion-function ((,typevar (eql ',name)))
           #'(lambda (,value) ,@body)))))

Obviously the former requires:

  (defun conversion-function (name)
    (get name 'conversion-function))

while the latter at least implies:

  (defgeneric conversion-function (name))

-Peter

Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp

From: Pascal Costanza
Subject: Re: Which do you like better?
Date: 
Message-ID: <cjkvpj$oau$1@newsreader2.netcologne.de>
Peter Seibel wrote:
> Suppose as part of some macrology I need a function (to be executed at
> macroexpansion time) that takes a symbol and returns a function that
> converts a value to the "type" named by the symbol. "Type" is in
> quotes because it's not necessarily a Lisp type--just a symbol. The
> mapping will be defined via a macro define-type-conversion. Here are
> two ways to implement that macro. Anyone have any strong feelings
> and/or arguments that one is better than the other?
> 
>   (defmacro define-type-conversion (name (value) &body body)
>     `(eval-when (:compile-toplevel :load-toplevel :execute)
>        (setf (get ',name 'conversion-function)
>              #'(lambda (,value) ,@body))))
> 
>   (defmacro define-type-conversion (name (value) &body body)
>     (with-gensyms (typevar)
>       `(eval-when (:compile-toplevel :load-toplevel :execute)
>          (defmethod conversion-function ((,typevar (eql ',name)))
>            #'(lambda (,value) ,@body)))))

I think that the property lists of symbols should be used sparingly, 
because their efficiency decreases with each property.

Furthermore I think it should be easier to debug your program if such a 
feature is not distributed across many symbols. The method can be 
inspected and single methods removed or changed.

What about a simple map?

(defvar *conversion-functions* nil)

(defun add-type-conversion (name function)
   (setf (getf name *conversion-functions*)
         function))

(defun conversion-function (name)
   (getf name *conversion-functions*))



Pascal

-- 
Tyler: "How's that working out for you?"
Jack: "Great."
Tyler: "Keep it up, then."
From: Peter Seibel
Subject: Re: Which do you like better?
Date: 
Message-ID: <m33c0u30zh.fsf@javamonkey.com>
Pascal Costanza <········@web.de> writes:

> Peter Seibel wrote:
>> Suppose as part of some macrology I need a function (to be executed at
>> macroexpansion time) that takes a symbol and returns a function that
>> converts a value to the "type" named by the symbol. "Type" is in
>> quotes because it's not necessarily a Lisp type--just a symbol. The
>> mapping will be defined via a macro define-type-conversion. Here are
>> two ways to implement that macro. Anyone have any strong feelings
>> and/or arguments that one is better than the other?
>>   (defmacro define-type-conversion (name (value) &body body)
>>     `(eval-when (:compile-toplevel :load-toplevel :execute)
>>        (setf (get ',name 'conversion-function)
>>              #'(lambda (,value) ,@body))))
>>   (defmacro define-type-conversion (name (value) &body body)
>>     (with-gensyms (typevar)
>>       `(eval-when (:compile-toplevel :load-toplevel :execute)
>>          (defmethod conversion-function ((,typevar (eql ',name)))
>>            #'(lambda (,value) ,@body)))))
>
> I think that the property lists of symbols should be used sparingly,
> because their efficiency decreases with each property.

Sure. But enough to matter. My rule of thumb is to only use symbol's
property list for storing information needed by macros (i.e. stuff
that is used at compile-time) on the assumption that a tiny speed hit
there really doesn't matter.)
>
> Furthermore I think it should be easier to debug your program if
> such a feature is not distributed across many symbols. The method
> can be inspected and single methods removed or changed.

That's a good point.

> What about a simple map?
>
> (defvar *conversion-functions* nil)
>
> (defun add-type-conversion (name function)
>    (setf (getf name *conversion-functions*)
>          function))
>
> (defun conversion-function (name)
>    (getf name *conversion-functions*))

I've done this in the past and the "problem" I've run into is that the
hash can get cluttered with symbols. E.g.

  (add-type-conversion 'x:foo #'(lambda (blah) ...))

  (unintern 'x:foo)

or 

  (delete-package :x)

then

  (add-type-conversion 'x:foo #'(lambda (blah) (something-else)))

Now, it's unlikely that in any given session one will do this enough
times for it to matter in any practical sense. But it does irk me.
Hanging information about a symbol on its plist doesn't have this
problem as the information attached to the symbol becomes garbage at
the same time as the symbol. Also, using the symbol as a key in a
hashtable will keep it from ever becoming garbage, even if it is
uninterned. (Yeah, I know, I could use any of the many implementation
specific weak-hash-tables to solve that problem.)

-Peter

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

         Lisp is the red pill. -- John Fraser, comp.lang.lisp