From: ·············@gmail.com
Subject: equal
Date: 
Message-ID: <1187369704.674273.219090@e9g2000prf.googlegroups.com>
Hi everyone,

I'm learning Lisp by myself using the book "Essential Lisp". In one of
the exercises I'm asked to define equal
in term of eql. This is my solution:

(defun my-equal (x y)
  (cond ((eql x y) t)
	(t (my-equal-aux x y))))

(defun my-equal-aux (x y)
  (cond ((and (null x) (null y)) t)
	((or (null x) (null y)) nil)
	((listp (car x)) (and (my-equal (car x) (car y))
			      (my-equal (cdr x) (cdr y))))
	((not (eql (car x) (car y))) nil)
	(t (my-equal (cdr x) (cdr y)))))

So far it behaves similar to the built-in equal. However I feel that
my answer is verbose. This is the answer in the book:

(defun my-equal (x y)
  (cond ((eql x y) t)
	(t (and (my-equal (car x) (car y))
		(my-equal (cdr x) (cdr y))))))

But when I tested this answer it worked only when two list are
actually equal. When they are not equal then there's an error message
saying something like cannot take the car of an atom.

Could you shed some lights?

Thanks.

Mark.

From: smallpond
Subject: Re: equal
Date: 
Message-ID: <1187383292.917990.264450@w3g2000hsg.googlegroups.com>
On Aug 17, 12:55 pm, ·············@gmail.com wrote:
> Hi everyone,
>
> I'm learning Lisp by myself using the book "Essential Lisp". In one of
> the exercises I'm asked to define equal
> in term of eql. This is my solution:
>
> (defun my-equal (x y)
>   (cond ((eql x y) t)
>         (t (my-equal-aux x y))))
>
> (defun my-equal-aux (x y)
>   (cond ((and (null x) (null y)) t)
>         ((or (null x) (null y)) nil)
>         ((listp (car x)) (and (my-equal (car x) (car y))
>                               (my-equal (cdr x) (cdr y))))
>         ((not (eql (car x) (car y))) nil)
>         (t (my-equal (cdr x) (cdr y)))))
>
> So far it behaves similar to the built-in equal. However I feel that
> my answer is verbose. This is the answer in the book:
>
> (defun my-equal (x y)
>   (cond ((eql x y) t)
>         (t (and (my-equal (car x) (car y))
>                 (my-equal (cdr x) (cdr y))))))
>
> But when I tested this answer it worked only when two list are
> actually equal. When they are not equal then there's an error message
> saying something like cannot take the car of an atom.
>
> Could you shed some lights?
>
> Thanks.
>
> Mark.

You want to do just two cases: use eql for atoms and the
recursive function for lists, so write it as two cases
using if <test> <then-part> <else-part>.

(defun my-equal (x y)
  (if (or (atom x) (atom y))
      (eql x y)
      (and (my-equal (car x) (car y))
           (my-equal (cdr x) (cdr y)))))

-- S
From: ·············@gmail.com
Subject: Re: equal
Date: 
Message-ID: <1187385235.338675.320280@x40g2000prg.googlegroups.com>
On 17 ao�t, 14:41, smallpond <·········@juno.com> wrote:
> On Aug 17, 12:55 pm, ·············@gmail.com wrote:
>
>
>
>
>
> > Hi everyone,
>
> > I'm learning Lisp by myself using the book "Essential Lisp". In one of
> > the exercises I'm asked to define equal
> > in term of eql. This is my solution:
>
> > (defun my-equal (x y)
> >   (cond ((eql x y) t)
> >         (t (my-equal-aux x y))))
>
> > (defun my-equal-aux (x y)
> >   (cond ((and (null x) (null y)) t)
> >         ((or (null x) (null y)) nil)
> >         ((listp (car x)) (and (my-equal (car x) (car y))
> >                               (my-equal (cdr x) (cdr y))))
> >         ((not (eql (car x) (car y))) nil)
> >         (t (my-equal (cdr x) (cdr y)))))
>
> > So far it behaves similar to the built-in equal. However I feel that
> > my answer is verbose. This is the answer in the book:
>
> > (defun my-equal (x y)
> >   (cond ((eql x y) t)
> >         (t (and (my-equal (car x) (car y))
> >                 (my-equal (cdr x) (cdr y))))))
>
> > But when I tested this answer it worked only when two list are
> > actually equal. When they are not equal then there's an error message
> > saying something like cannot take the car of an atom.
>
> > Could you shed some lights?
>
> > Thanks.
>
> > Mark.
>
> You want to do just two cases: use eql for atoms and the
> recursive function for lists, so write it as two cases
> using if <test> <then-part> <else-part>.
>
> (defun my-equal (x y)
>   (if (or (atom x) (atom y))
>       (eql x y)
>       (and (my-equal (car x) (car y))
>            (my-equal (cdr x) (cdr y)))))
>
> -- S- Masquer le texte des messages pr�c�dents -
>
> - Afficher le texte des messages pr�c�dents -

Thank you very much. Your analysis is superb.

Mark.
From: Pascal Bourguignon
Subject: Re: equal
Date: 
Message-ID: <87sl6ham3b.fsf@thalassa.informatimago.com>
smallpond <·········@juno.com> writes:

> On Aug 17, 12:55 pm, ·············@gmail.com wrote:
>> Hi everyone,
>>
>> I'm learning Lisp by myself using the book "Essential Lisp". In one of
>> the exercises I'm asked to define equal
>> in term of eql. This is my solution:
>>
>> (defun my-equal (x y)
>>   (cond ((eql x y) t)
>>         (t (my-equal-aux x y))))
>>
>> (defun my-equal-aux (x y)
>>   (cond ((and (null x) (null y)) t)
>>         ((or (null x) (null y)) nil)
>>         ((listp (car x)) (and (my-equal (car x) (car y))
>>                               (my-equal (cdr x) (cdr y))))
>>         ((not (eql (car x) (car y))) nil)
>>         (t (my-equal (cdr x) (cdr y)))))
>>
>> So far it behaves similar to the built-in equal. However I feel that
>> my answer is verbose. This is the answer in the book:
>>
>> (defun my-equal (x y)
>>   (cond ((eql x y) t)
>>         (t (and (my-equal (car x) (car y))
>>                 (my-equal (cdr x) (cdr y))))))
>>
>> But when I tested this answer it worked only when two list are
>> actually equal. When they are not equal then there's an error message
>> saying something like cannot take the car of an atom.
>>
>> Could you shed some lights?
>>
>> Thanks.
>>
>> Mark.
>
> You want to do just two cases: use eql for atoms and the
> recursive function for lists, so write it as two cases
> using if <test> <then-part> <else-part>.
>
> (defun my-equal (x y)
>   (if (or (atom x) (atom y))
>       (eql x y)
>       (and (my-equal (car x) (car y))
>            (my-equal (cdr x) (cdr y)))))

This would not conform to CL:EQUAL specification.  But this may be
what's specified by the "Essential Lisp" exercise.

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

NOTE: The most fundamental particles in this product are held
together by a "gluing" force about which little is currently known
and whose adhesive power can therefore not be permanently
guaranteed.
From: ·······@gmail.com
Subject: Re: equal
Date: 
Message-ID: <1187372046.185204.299010@d55g2000hsg.googlegroups.com>
On Aug 17, 12:55 pm, ·············@gmail.com wrote:
> Hi everyone,
>
> I'm learning Lisp by myself using the book "Essential Lisp". In one of
> the exercises I'm asked to define equal
> in term of eql. This is my solution:
>
> (defun my-equal (x y)
>   (cond ((eql x y) t)
>         (t (my-equal-aux x y))))
>
> (defun my-equal-aux (x y)
>   (cond ((and (null x) (null y)) t)
>         ((or (null x) (null y)) nil)
>         ((listp (car x)) (and (my-equal (car x) (car y))
>                               (my-equal (cdr x) (cdr y))))
>         ((not (eql (car x) (car y))) nil)
>         (t (my-equal (cdr x) (cdr y)))))
>
> So far it behaves similar to the built-in equal. However I feel that
> my answer is verbose. This is the answer in the book:
>
> (defun my-equal (x y)
>   (cond ((eql x y) t)
>         (t (and (my-equal (car x) (car y))
>                 (my-equal (cdr x) (cdr y))))))
>
> But when I tested this answer it worked only when two list are
> actually equal. When they are not equal then there's an error message
> saying something like cannot take the car of an atom.
>
> Could you shed some lights?
>
> Thanks.
>
> Mark.

I'd say you're right on the given solution being wrong. For starters,
http://www.lisp.org/HyperSpec/Body/fun_equal.html , equal is defined
for other stuff like strings...

I think the book is missing a second cond clause like ((or (atom x)
(atom y)) nil).

You can just omit the last two clauses in your cond - since you
already test (listp x) in the prior clause, any x that falls down to
those clauses will not be a list, ie, it will bug when you call (car
x) or (cdr x) on it. For example (my-equal "foo" "foo"). And I think
testing for null is excessive in the first two clauses of that cond,
since (eql nil nil) is true in the first part of the my-equal function.