From: Vladimir Zolotykh
Subject: predicate function
Date: 
Message-ID: <3C1A1E99.2BE96701@eurocom.od.ua>
Sometimes I've read

(defgeneric regular-user-p (user)
  (:method ((u regular-user)) t)
  (:method (u) nil))

Is this has significant advantage comparing with

(defun regular-user-p (user)
  (typep user 'regular-user))

Which one is more prefferable ?

-- 
Vladimir Zolotykh                         ······@eurocom.od.ua

From: Kent M Pitman
Subject: Re: predicate function
Date: 
Message-ID: <sfwn10l6aur.fsf@shell01.TheWorld.com>
Vladimir Zolotykh <······@eurocom.od.ua> writes:

> Sometimes I've read
> 
> (defgeneric regular-user-p (user)
>   (:method ((u regular-user)) t)
>   (:method (u) nil))
> 
> Is this has significant advantage comparing with
> 
> (defun regular-user-p (user)
>   (typep user 'regular-user))
> 
> Which one is more prefferable ?

Well, it's not the syntax that matters.

(defmethod regular-user-p ((x t)) nil)
(defmethod regular-user-p ((x regular-user)) t)

is fine. But this form makes sure you are ONLY doing type discrimination
when doing regular-user-p and that you are not wasting time looking for
type expansions of REGULAR-USER, etc. (see DEFTYPE).  The version with
TYPEP might be as fast, but in practice has a good chance of being slower
if not open-coded just right.

Writing it with methods will generally cause you not to do accidental
forward references, too.  You can't do method definitions until after
the requisite DEFCLASS.  But you _can_ do the TYPEP definition you
suggest before the DEFCLASS.  Once in a while, this is useful because
you need to put the type predicate before the class.  But often it
just means the compiler will compile the call to TYPEP more slowly
than should be needed, and in some implementations it will do so
without telling you...
From: Rahul Jain
Subject: Re: predicate function
Date: 
Message-ID: <87r8pxmmk7.fsf@photino.sid.rice.edu>
Vladimir Zolotykh <······@eurocom.od.ua> writes:

> Sometimes I've read
> 
> (defgeneric regular-user-p (user)
>   (:method ((u regular-user)) t)
>   (:method (u) nil))
> 
> Is this has significant advantage comparing with
> 
> (defun regular-user-p (user)
>   (typep user 'regular-user))
> 
> Which one is more prefferable ?

I think this is an important way in which CLOS differs from other
object systems. Protocols are handled via generic-functions, and types
are handled via classes. I first saw this distinction clearly when
reading the CLIM spec and really like the idea. Instead of using the
type system to indicate what an object "can do", it indicates what the
object is "made of". So I'd have the regular-user-p function be a g-f
indicating whether a specific object's type supports the
"regular-user" protocol, and leave the initial definition as you have
it. For inspecting the actual type of an object, I think explicit use
of typep is appropriate.

I think it's (un)fortunately non-trivial to actually verify that all
types for which regular-user-p returns t actually support the full
protocol. The dynamic nature of the language means that this can
change over time, and I wouldn't want to prevent an object from being
seen as a "regular-user" if it doesn't implement some part of the
functionality which doesn't even matter in the current usage of the
object. After all, I can always define it later :)

-- 
-> -/-                       - Rahul Jain -                       -\- <-
-> -\- http://linux.rice.edu/~rahul -=- ·················@usa.net -/- <-
-> -/- "I never could get the hang of Thursdays." - HHGTTG by DNA -\- <-
|--|--------|--------------|----|-------------|------|---------|-----|-|
   Version 11.423.999.220020101.23.50110101.042
   (c)1996-2000, All rights reserved. Disclaimer available upon request.