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

type-of



    Date: Wed, 19 Nov 86 09:11:01 MST
    From: sandra%utah-orion@utah-cs.arpa (Sandra J Loosemore)

	From: RWK@YUKON.SCRC.Symbolics.COM (Robert W. Kerns)
	Date: 18 Nov 86 21:04:00 GMT

	Here is an example of completely-portable code which depends on
	TYPE-OF returning the MOST specific type.

	(defun store-in-array-if-fits (object array &rest indicies)
	  (let ((object-type (type-of object))
		(array-type (array-element-type array)))
	    (if (subtypep object-type array-type)
	      ;; If the object fits, store it
		(setf (apply #'aref array indicies) object)
	      ;; Doesn't fit, so store 0 instead.
		(setf (apply #'aref array indicies) 0))))

    Sorry, I can't buy this motivation.  All this example illustrates is that
    there is a good reason for having the TYPEP function around.

(defun typep (object type)
  (subtypep (type-of object) type))

Yes, my example is a bit oversimplified; I was more interested in
demonstrating portability than necessity.  And the "important half"
of TYPEP is SUBTYPEP, not TYPE-OF.  But TYPEP doesn't let you
make the decision about the type separately from the object in
question.

    As it happens, in PCLS, TYPE-OF does go through a considerable amount of 
    work to find the most specific type that it can.  So, (TYPE-OF 0) returns 
    BIT, which is correct but largely useless.  My "gut feeling" is that what
    the user probably wants is either FIXNUM or INTEGER --  something which 
    indicates how the object is represented internally, or (in other words) 
    one of the set of types which CLtL says are disjoint.
If the user is writing his code properly, he is using
type-comparison (i.e. SUBTYPEP), so he doesn't really
care.  But your "gut feeling" is right, he probably
doesn't care about anything more specific than
FIXNUM.

That's why I think it would be advantagious to more
precisely specify TYPE-OF.  Right now the spec could
be read as requiring (TYPE-OF 0) => BIT.  If we specify
a "least specific" type (FIXNUM in this case), than
any implementation which returns something *at least*
as specific as FIXNUM is fine.  If an implementation
has reason for being more specific, however, it should
be free to do so.

    I'll have to agree that TYPE-OF as defined now is pretty bogus.  The only 
    place I've ever had reason to use TYPE-OF in real code was to get a type
    to pass to COERCE or CONCATENATE, etc., when I wanted to ensure that two
    objects were of the same type; for example, both lists or whatever.  But 
    this is full of holes, too.  For example, 

	(coerce '#(a b c) (type-of (list)))

    may fail, depending on whether your favorite implementation thinks NIL is
    of type NULL, LIST, or SYMBOL.  I ended up writing a specialized function
    to do what I wanted, without relying on TYPE-OF.

This is just a matter of TYPE-OF not being specific enough
together with COERCE not being general enough.  If TYPE-OF
is properly specific (i.e. NULL), and COERCE finds the
"least supertype" of the argument type that it supports
(for example, if you wrote it with TYPECASE or SUBTYPEP,
rather than EQL), then there's no problem.

Our entire user-interface in Release 7 is based on just
type sort of question.  It is fundamental to any theory
of TYPEP, as well.  I freely admit that it isn't often
called, but that's not a reason to eliminate it, or to
leave it sloppily specified.

    In short, I am not convinced that TYPE-OF would be particularly useful even
    if its definition were firmed up more.  If nobody has any good use for this
    function, arguing over how it should behave is rather pointless.
I think your own example contradicts this position.