From: Kalle Olavi Niemitalo
Subject: Specializing on NULL vs. (EQL NIL)
Date: 
Message-ID: <87r8t5vetm.fsf@Astalo.y2000.kon.iki.fi>
Yesterday, I asked about a loop that collected
(if piece (piece-mnemonic-char piece) #\Space).

Today, I realized all calls of PIECE-MNEMONIC-CHAR are likely to
have that check and I could as well make the function accept NIL
and return #\Space.  It is a generic function so I do that by
defining a new method.  (C++ made me not think of this before.)

  (defmethod piece-mnemonic-char (piece null) #\Space)

  (defmethod piece-mnemonic-char (piece (eql nil)) #\Space)

Which of these would you prefer?  I think the second one might be
clearer, because the NULL function checks for an empty list and
PIECE is normally not a list.

From: Thomas F. Burdick
Subject: Re: Specializing on NULL vs. (EQL NIL)
Date: 
Message-ID: <xcvitehv7ag.fsf@apocalypse.OCF.Berkeley.EDU>
Kalle Olavi Niemitalo <···@iki.fi> writes:

> Yesterday, I asked about a loop that collected
> (if piece (piece-mnemonic-char piece) #\Space).
> 
> Today, I realized all calls of PIECE-MNEMONIC-CHAR are likely to
> have that check and I could as well make the function accept NIL
> and return #\Space.  It is a generic function so I do that by
> defining a new method.  (C++ made me not think of this before.)

 (That was one of the best things learning CL, realizing when you were
  breaking out of C++ thinking :)

>   (defmethod piece-mnemonic-char (piece null) #\Space)
> 
>   (defmethod piece-mnemonic-char (piece (eql nil)) #\Space)
> 
> Which of these would you prefer?  I think the second one might be
> clearer, because the NULL function checks for an empty list and
> PIECE is normally not a list.

I think you just answered your own question.
From: Tim Moore
Subject: Re: Specializing on NULL vs. (EQL NIL)
Date: 
Message-ID: <9o5qtb$4v8$0@216.39.145.192>
On 17 Sep 2001, Thomas F. Burdick wrote:

> Kalle Olavi Niemitalo <···@iki.fi> writes:
> 
> >   (defmethod piece-mnemonic-char (piece null) #\Space)
> > 
> >   (defmethod piece-mnemonic-char (piece (eql nil)) #\Space)
> > 
> > Which of these would you prefer?  I think the second one might be
> > clearer, because the NULL function checks for an empty list and
> > PIECE is normally not a list.
> 
> I think you just answered your own question.

I think it's a matter of preference.  I'd slightly prefer the first form
because the class NULL includes only NIL, whether or not you take it to
mean the empty list or false, and why not use it if you've got it? :)

Tim
From: Barry Margolin
Subject: Re: Specializing on NULL vs. (EQL NIL)
Date: 
Message-ID: <jaup7.20$0s2.4155@burlma1-snr2>
In article <··············@Astalo.y2000.kon.iki.fi>,
Kalle Olavi Niemitalo  <···@iki.fi> wrote:
>Yesterday, I asked about a loop that collected
>(if piece (piece-mnemonic-char piece) #\Space).
>
>Today, I realized all calls of PIECE-MNEMONIC-CHAR are likely to
>have that check and I could as well make the function accept NIL
>and return #\Space.  It is a generic function so I do that by
>defining a new method.  (C++ made me not think of this before.)
>
>  (defmethod piece-mnemonic-char (piece null) #\Space)
>
>  (defmethod piece-mnemonic-char (piece (eql nil)) #\Space)
>
>Which of these would you prefer?  I think the second one might be
>clearer, because the NULL function checks for an empty list and
>PIECE is normally not a list.

What does the NULL function have to do with this?  The only reference you
have to NULL is in an argument specializer, which is a data type, not a
function name.  The NULL data type is the type that just includes the
object NIL.

Since most method dispatching is on types rather than EQL, it's likely that
most CLOS implementations optimize it better.  They might recognize the
equivalence of NULL and (EQL NIL), but I wouldn't bet on it.

And even disregarding optimization concerns (which you shouldn't worry
about unless you actually determine that there's a performance problem, and
it doesn't seem like you were asking about), other programmers reading your
code are likely to find type specialization more understandable than EQL
specialization.  EQL specializers are often used for special cases, whereas
type dispatching is the normal style.

-- 
Barry Margolin, ······@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Kalle Olavi Niemitalo
Subject: Re: Specializing on NULL vs. (EQL NIL)
Date: 
Message-ID: <87wv2xt5yh.fsf@Astalo.y2000.kon.iki.fi>
Barry Margolin <······@genuity.net> writes:

> What does the NULL function have to do with this?  The only reference you
> have to NULL is in an argument specializer, which is a data type, not a
> function name.

I thought the distinction between the NULL and NOT functions
would extend to the NULL type.

The description of the NULL function says that

  (null object) == (typep object 'null) == (eq object '())

No such equivalence is listed for the NOT function.

Is it nevertheless good style to use the NULL type with things
other than lists?

> They might recognize the
> equivalence of NULL and (EQL NIL), but I wouldn't bet on it.

CMUCL let me specialize the same function on both.
Does that mean it did not recognize the equivalence?

> EQL specializers are often used for special cases, whereas
> type dispatching is the normal style.

NIL is a special case here: the function is called
PIECE-MNEMONIC-CHAR, and NIL is not really a piece.
Most "piece" functions won't have methods for it.
From: Barry Margolin
Subject: Re: Specializing on NULL vs. (EQL NIL)
Date: 
Message-ID: <JCKp7.11$N4.689@burlma1-snr2>
In article <··············@Astalo.y2000.kon.iki.fi>,
Kalle Olavi Niemitalo  <···@iki.fi> wrote:
>Barry Margolin <······@genuity.net> writes:
>
>> What does the NULL function have to do with this?  The only reference you
>> have to NULL is in an argument specializer, which is a data type, not a
>> function name.
>
>I thought the distinction between the NULL and NOT functions
>would extend to the NULL type.
>
>The description of the NULL function says that
>
>  (null object) == (typep object 'null) == (eq object '())
>
>No such equivalence is listed for the NOT function.
>
>Is it nevertheless good style to use the NULL type with things
>other than lists?

When you're defining methods, the things can be anything.  The specializer
simply says that this particular method will only apply to objects of that
specific type.  If the function can be called with things other than lists,
then other methods will handle those cases.

>> They might recognize the
>> equivalence of NULL and (EQL NIL), but I wouldn't bet on it.
>
>CMUCL let me specialize the same function on both.
>Does that mean it did not recognize the equivalence?

The question is whether the same code is generated.  They both have the
same high-level behavior, since the only object in the NULL class is NIL.

>
>> EQL specializers are often used for special cases, whereas
>> type dispatching is the normal style.
>
>NIL is a special case here: the function is called
>PIECE-MNEMONIC-CHAR, and NIL is not really a piece.
>Most "piece" functions won't have methods for it.

But NIL is so special throughout the language that there's a special class
defined for it.  Perhaps a better way to have said it is that EQL is
typically used when you need to deal with cases more specific than the type
hierarchy supports.  E.g.

(defmethod factorial ((n (eql 1)))
  1)
(defmethod factorial ((n integer))
  (* n (factorial (1- n))))

EQL needs to be used here because you need to distinguish between different
objects within the integer type.

-- 
Barry Margolin, ······@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.