From: Axel Schairer
Subject: equal vs. equalp
Date: 
Message-ID: <ydjn2brdfjm.fsf@dfki.de>
Comparing structures with equal does not compare the components
recursively.  So, I assumed, equalp would be what I needed to do that.
However, equalp has the effect of comparing strings without
distinguishing case.  E.g.

(defstruct a b)
(equal (make-a :b "string") (make-a :b "string"))
	=> NIL		;;; I need T
(equalp (make-a :b "string") (make-a :b "string"))
	=> T		;;; OK
(equalp (make-a :b "string") (make-a :b "STRING"))
	=> T		;;; I need false

CLTL2 says (p. 109): <cite>If neither equal nor equalp is found to be
appropriate in a particular situation, programmers are encouraged to
create another operator that is appropriate rather than blame equal or
equalp for ``doing the wrong thing.''</cite>

Now, I find it difficult to come up with such an operator.  My first
idea was to have something like

(defun same (x y)
  (cond ((structurep x)
         (map-over-components 'same
                              x y))
        (t (equal x y))))

except, of course, that structurep and map-over-components do not
exist.  Note that CLOS is not a solution since the issue came up
precisely when porting a package, which defined same as a generic
function, to a non-CLOS environment.

Any ideas?  Thanks.

Axel

From: Kent M Pitman
Subject: Re: equal vs. equalp
Date: 
Message-ID: <sfwaf7rlowt.fsf@world.std.com>
Axel Schairer <········@dfki.de> writes:

> Comparing structures with equal does not compare the components
> recursively.  So, I assumed, equalp would be what I needed to do that.
> However, equalp has the effect of comparing strings without
> distinguishing case.  
> [...]
> Any ideas?  Thanks.

EQUAL and EQUALP are just arbitrarily chosen predicates among a huge
space of possible predicates.  They are offered out of tradition but
they are meaningless conceptually--they mean exactly what they are 
defined to mean, but there is no uniquely determined general purpose
equality predicate.  You must create your own.

My personal conclusion is that EQUAL and EQUALP cannot be fixed in
general without an extra argument identifying the "intention" or
"view" to be used in the comparison.  For details, see my EQUAL Rights
article (not to be confused with a similarly titled article by Henry
Baker came out in another forum at about the same time--I guess it was
just a title that cried out to be used :-).  Mine is at:

 http://world.std.com/~pitman/PS/EQUAL.html

Actually, as I recall, Baker's paper is also worth reading, though
it's longer and takes a kind of different direction than mine.
(I recall his bibliography is probably as long as my whole paper...)
I don't have a URL for it, but last I checked he had a paper 
repository at netcom.com and a web search might turn it up.
From: Barry Margolin
Subject: Re: equal vs. equalp
Date: 
Message-ID: <Nz3e1.36$rH4.668674@cam-news-reader1.bbnplanet.com>
In article <···············@dfki.de>, Axel Schairer  <········@dfki.de> wrote:
>CLTL2 says (p. 109): <cite>If neither equal nor equalp is found to be
>appropriate in a particular situation, programmers are encouraged to
>create another operator that is appropriate rather than blame equal or
>equalp for ``doing the wrong thing.''</cite>
>
>Now, I find it difficult to come up with such an operator.  My first
>idea was to have something like
>
>(defun same (x y)
>  (cond ((structurep x)
>         (map-over-components 'same
>                              x y))
>        (t (equal x y))))
>
>except, of course, that structurep and map-over-components do not
>exist.  Note that CLOS is not a solution since the issue came up
>precisely when porting a package, which defined same as a generic
>function, to a non-CLOS environment.

You're expected to write something specific to the structures used in your
application.

(defun same-a (x y)
  (cond ((typep x 'a) (same-a (a-b x) (a-b y)))
        (t (equal x y))))

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Cambridge, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
From: Marco Antoniotti
Subject: Re: equal vs. equalp
Date: 
Message-ID: <lwsoldvirt.fsf@galvani.parades.rm.cnr.it>
Barry Margolin <······@bbnplanet.com> writes:

> In article <···············@dfki.de>, Axel Schairer
> <········@dfki.de> wrote:
>	...
> >exist.  Note that CLOS is not a solution since the issue came up
> >precisely when porting a package, which defined same as a generic
> >function, to a non-CLOS environment.
> 
> You're expected to write something specific to the structures used in your
> application.
> 
> (defun same-a (x y)
>   (cond ((typep x 'a) (same-a (a-b x) (a-b y)))
>         (t (equal x y))))
> 

As per the Hyperspec, if we have two structures, EQUALP returns "true":

"If two structures S1 and S2 have the same class and the value of each
slot in S1 is the same under equalp as the value of the corresponding
slot in S2."

There is also a caveat at the end of the page.

-- 
Marco Antoniotti ===========================================
PARADES, Via San Pantaleo 66, I-00186 Rome, ITALY
tel. +39 - (0)6 - 68 80 79 23, fax. +39 - (0)6 - 68 80 79 26
http://www.parades.rm.cnr.it
From: Axel Schairer
Subject: Re: equal vs. equalp
Date: 
Message-ID: <ydj1zswdw5g.fsf@dfki.de>
Thanks to Kent, Barry, and Marco for their comments.  I understand the
issues involved (equal/equalp are arbitrarily chosen predicates and
cannot be fixed globally; I am expected to write a predicate specific
to my structure). (I am afraid I didn't get the message of Marco's
post.)

My question, sorry if I did not get that across in the first post, is:
How can I write something similar to equalp except that characters are
compared in a case sensitive manner?  The ideas I came up with were:

1) Write a specific predicate for every structure, make a predicate of
   two types that dispatches on the type of its first argument (see
   Barry's post) and calls the appropriate special predicate.

This does not work for me because structures are defined all over the
source, and there is no place where we know that all structures have
been defined.  Thus there is no natural place to assemble the
dispatching predicate.  And redefining the predicate on every new
structure definition gives lots of warnings (redefining function ...)
which I do not want other programmers to be bothered with.

2) Write a predicate that calls equal on its arguments iff they are
   not structures and compares the structures' components otherwise.

I don't know how to find out whether something is a structure, and how
to find all its slots.  Plus I suspect there is no portable way to do
it.

3) Record all the names of the structures you want to be descended in
   a special variable, say *defined-termtypes*.  When defining such a
   structure, put the specialised predicate on the property list of
   the symbol naming the type.  (This is all done consistently within a
   macro.)  Write your predicate as follows:

   (defun same (x y)
     (let ((xtype (type-of x))
           (ytype (type-of y)))
       (cond ((and (member xtype *defined-termtypes*)
                   (eq xtype ytype))
              (funcall (get xtype 'equality-predicate)
                       x y))
             (t (equal x y)))))


I.e. test whether x and y have the same type and wether it is recorded
in the special variable *defined-termtypes*.  If yes the equality
predicate from the property list of the symbol naming the type is
applied to the two arguments.  Now, this seems to me to be just awful.

I do not want to discuss whether Lisp should give me the predicate I
would like to have.  Rather I am looking for a viable (and sensible
way) to implement it myself.

Thanks for any suggestions,

Axel
From: Axel Schairer
Subject: Correction: equal vs. equalp
Date: 
Message-ID: <ydjzpfkcgdu.fsf_-_@dfki.de>
Axel Schairer <········@dfki.de> writes:
> 1) Write a specific predicate for every structure, make a predicate of
>    two types that dispatches on the type of its first argument (see

Sorry:  Read `a predicate of two arguments'.
From: Barry Margolin
Subject: Re: equal vs. equalp
Date: 
Message-ID: <pxSf1.71$Fr5.738911@cam-news-reader1.bbnplanet.com>
In article <···············@dfki.de>, Axel Schairer  <········@dfki.de> wrote:
>3) Record all the names of the structures you want to be descended in
>   a special variable, say *defined-termtypes*.  When defining such a
>   structure, put the specialised predicate on the property list of
>   the symbol naming the type.  (This is all done consistently within a
>   macro.)  Write your predicate as follows:
>
>   (defun same (x y)
>     (let ((xtype (type-of x))
>           (ytype (type-of y)))
>       (cond ((and (member xtype *defined-termtypes*)
>                   (eq xtype ytype))
>              (funcall (get xtype 'equality-predicate)
>                       x y))
>             (t (equal x y)))))

Since structure types also become class names, you can do this more
elegantly using CLOS.  Your EQUALITY-PREDICATE property list is analogous
to calling a generic function, so you could have your macro define:

`(defmethod same ((x ,type) (y ,type))
    ...)

I was a bit concerned about whether this is correct if structure subtypes
are created using :INCLUDE -- intuitively, I expected that the subtype
would also be a subclass, and the wrong thing could happen if the method
for the supertype were invoked on subtype structures.  But as far as I can
tell, the structure type hierarchy is not supposed to be mirrored in the
class hierarchy.

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Cambridge, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
From: Barry Margolin
Subject: Re: equal vs. equalp
Date: 
Message-ID: <xJTf1.76$Fr5.738911@cam-news-reader1.bbnplanet.com>
In article <···················@cam-news-reader1.bbnplanet.com>,
Barry Margolin  <······@bbnplanet.com> wrote:
>`(defmethod same ((x ,type) (y ,type))
>    ...)
>
>I was a bit concerned about whether this is correct if structure subtypes
>are created using :INCLUDE -- intuitively, I expected that the subtype
>would also be a subclass, and the wrong thing could happen if the method
>for the supertype were invoked on subtype structures.  But as far as I can
>tell, the structure type hierarchy is not supposed to be mirrored in the
>class hierarchy.

I take it back, my concern is valid.  CLtL2 p.781 says "The :INCLUDE
option of DEFSTRUCT creates a direct subclass of the class that corresponds
to the included structure."

I'm having trouble finding the corresponding statement in the CLHS.
Section 4.2.2 Type Relationships
 <http://www.harlequin.com/education/books/HyperSpec/Body/sec_4-2-2.html>
says, that structure types are disjoint unless they're related by :INCLUDE,
but doesn't say anything about classes.

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Cambridge, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.