From: ab talebi
Subject: CAR/CDR Recursion
Date: 
Message-ID: <3bd5dbd2.2944715@news.uio.no>
(defun james-age (x)
  (cond ((equal (car x) 'james) x)
        ((null x) nil)
        (t (list (james-age (car x))
                 (james-age (cdr x))))))


I have written this car/cdr recursion, but I don't get it to work and
I don't know why.
The idea is that this will take a nested list like:
((james 27) (peter 38) (james 12) (patric 32)) 
and returns all the james and their ages:
((james 27) (james 12))

From: Don Geddis
Subject: Re: CAR/CDR Recursion
Date: 
Message-ID: <m3adyivy35.fsf@jedi.tesserae.com>
············@yahoo.com (ab talebi) writes:
> (defun james-age (x)
>   (cond ((equal (car x) 'james) x)
>         ((null x) nil)
>         (t (list (james-age (car x))
>                  (james-age (cdr x))))))
> 
> I have written this car/cdr recursion, but I don't get it to work and
> I don't know why.
> The idea is that this will take a nested list like:
> ((james 27) (peter 38) (james 12) (patric 32)) 
> and returns all the james and their ages:
> ((james 27) (james 12))

I think your example will work if you change it like this:

(defun james-age (x)
  (cond ((and (eq (caar x) (caaddr x))) (list (car x) (caddr x)))
        ((equal (car x) 'james) x)
        ((null x) nil)
        (t (list (james-age (car x))
                 (james-age (cdr x))))))

_______________________________________________________________________________
Don Geddis                   www.overture.com               ······@overture.com
Vice President of Research and Development                   Phone 650-403-2220
Overture, 1820 Gateway Drive, Suite 360, San Mateo, CA 94404   Fax 650-403-2201
From: ab talebi
Subject: Re: CAR/CDR Recursion
Date: 
Message-ID: <6b58a68e.0110240918.13cb54@posting.google.com>
Don Geddis <······@overture.com> wrote in message news:<··············@jedi.tesserae.com>...
> ············@yahoo.com (ab talebi) writes:
> > (defun james-age (x)
> >   (cond ((equal (car x) 'james) x)
> >         ((null x) nil)
> >         (t (list (james-age (car x))
> >                  (james-age (cdr x))))))
> > 
> > I have written this car/cdr recursion, but I don't get it to work and
> > I don't know why.
> > The idea is that this will take a nested list like:
> > ((james 27) (peter 38) (james 12) (patric 32)) 
> > and returns all the james and their ages:
> > ((james 27) (james 12))
> 
> I think your example will work if you change it like this:
> 
> (defun james-age (x)
>   (cond ((and (eq (caar x) (caaddr x))) (list (car x) (caddr x)))
>         ((equal (car x) 'james) x)
>         ((null x) nil)
>         (t (list (james-age (car x))
>                  (james-age (cdr x))))))
> 
> _______________________________________________________________________________
> Don Geddis                   www.overture.com               ······@overture.com
> Vice President of Research and Development                   Phone 650-403-2220
> Overture, 1820 Gateway Drive, Suite 360, San Mateo, CA 94404   Fax 650-403-2201



There is something strenge with your code:
(james-age '((james 27) (peter 38) (james 12) (patric 32)))
returns:
((JAMES 27) (JAMES 12))  
which is fine but:
(james-age '((james 27) (james 12) (patric 32))) returns:
Error: Incorrect list structure (JAMES 27) for CAAR
From: Kenny Tilton
Subject: Re: CAR/CDR Recursion
Date: 
Message-ID: <3BD6172D.24C22611@nyc.rr.com>
Try this version:

(defun james-age (x &optional (debug :top))
  (format t "~&james-age> ~a ~a" debug x)
  (cond ((equal (car x) 'james) x)
        ((null x) nil)
        (t (list (james-age (car x) :carx)
                 (james-age (cdr x) :cdrx)))))

which is the same as yours with diagnostics which might help you a
little. you might consider adding more diagnostics to indicate the
return value (or use 'trace).

do you have to use recursion or can you use any CL function? good
exercise to work out the recursive approach, but CL includes a function
that does what you want.

kenny
clinisys


ab talebi wrote:
> 
> (defun james-age (x)
>   (cond ((equal (car x) 'james) x)
>         ((null x) nil)
>         (t (list (james-age (car x))
>                  (james-age (cdr x))))))
> 
> I have written this car/cdr recursion, but I don't get it to work and
> I don't know why.
> The idea is that this will take a nested list like:
> ((james 27) (peter 38) (james 12) (patric 32))
> and returns all the james and their ages:
> ((james 27) (james 12))
From: ab talebi
Subject: Re: CAR/CDR Recursion
Date: 
Message-ID: <6b58a68e.0110240821.6a6d472c@posting.google.com>
Thus this is a good excercise it is also a good programming skill to
write as short programs as possible. What function does CL include
that does a CAR/CDR recursion?



Kenny Tilton <·······@nyc.rr.com> wrote in message news:<·················@nyc.rr.com>...
> Try this version:
> 
> (defun james-age (x &optional (debug :top))
>   (format t "~&james-age> ~a ~a" debug x)
>   (cond ((equal (car x) 'james) x)
>         ((null x) nil)
>         (t (list (james-age (car x) :carx)
>                  (james-age (cdr x) :cdrx)))))
> 
> which is the same as yours with diagnostics which might help you a
> little. you might consider adding more diagnostics to indicate the
> return value (or use 'trace).
> 
> do you have to use recursion or can you use any CL function? good
> exercise to work out the recursive approach, but CL includes a function
> that does what you want.
> 
> kenny
> clinisys
> 
> 
> ab talebi wrote:
> > 
> > (defun james-age (x)
> >   (cond ((equal (car x) 'james) x)
> >         ((null x) nil)
> >         (t (list (james-age (car x))
> >                  (james-age (cdr x))))))
> > 
> > I have written this car/cdr recursion, but I don't get it to work and
> > I don't know why.
> > The idea is that this will take a nested list like:
> > ((james 27) (peter 38) (james 12) (patric 32))
> > and returns all the james and their ages:
> > ((james 27) (james 12))
From: Jeff Mincy
Subject: Re: CAR/CDR Recursion
Date: 
Message-ID: <d73dt1qd.fsf@antarres.muniversal.com>
············@yahoo.com (ab talebi) writes:
> Thus this is a good excercise it is also a good programming skill to
> write as short programs as possible. What function does CL include
> that does a CAR/CDR recursion?

You don't need to do recursion to process elements of a list, which is
all your function is really doing.   There are sequence functions and
mapping functions and iteration macros for processing lists.

> > ab talebi wrote:
> > > (defun james-age (x)
> > >   (cond ((equal (car x) 'james) x)
> > >         ((null x) nil)
> > >         (t (list (james-age (car x))
> > >                  (james-age (cdr x))))))
> > > 
> > > I have written this car/cdr recursion, but I don't get it to work and
> > > I don't know why.
> > > The idea is that this will take a nested list like:
> > > ((james 27) (peter 38) (james 12) (patric 32))
> > > and returns all the james and their ages:
> > > ((james 27) (james 12))

(defun jamesp (x) (and (consp x) (eq (car x) 'james)))
(setq list '((james 27) (peter 38) (james 12) (patric 32)))
(remove-if-not #'jamesp list)

-jeff
From: Alex Aris
Subject: Re: CAR/CDR Recursion
Date: 
Message-ID: <9r84mc$k03$1@hecate.umd.edu>
ab talebi (············@yahoo.com) wrote:
: (defun james-age (x)
:   (cond ((equal (car x) 'james) x)
:         ((null x) nil)
:         (t (list (james-age (car x))
:                  (james-age (cdr x))))))


: I have written this car/cdr recursion, but I don't get it to work and
: I don't know why.

first of all, you check 'james with car.
(car x) will return (james 27) if x is the list below.
So, the correct way, would be (car (car x)) or (caar x)

But this is not enough. Let's see:
After this modification, your defn becomes:

 (defun james-age (x)
   (cond ((equal (caar x) 'james) x)
         ((null x) nil)
         (t (list (james-age (car x))
                  (james-age (cdr x))))))

I don't know what you meant in the 4th line.
(james-age (car x)) will cause to apply car 
to a non-list value because you will call james-age with 
(james 27) as argument which doesn't have the same format as
you intended at first.


: The idea is that this will take a nested list like:
: ((james 27) (peter 38) (james 12) (patric 32)) 
: and returns all the james and their ages:
: ((james 27) (james 12))

When you write a recursive function, you first 
find a base case. It;s usually the smallest valid list.
And you may have () as the smalles. So, you write the
function handling base case first. 
What should it return?

> (james-age '())
NIL

right? because there are no pairs at all. So,

(defun james-age (x)
   (cond ( (null x)  nil )
          ...
                ))

   Now, you can consider the recursive case.
The trick is that you assume that somebody else has already
written james-age and it's READY for YOU there. You can use it freely
in your definition to solve a smaller problem.

    A smaller problem will be a smaller list, like
the cdr of the list, for instance.

    So, the recursive call will look like 
(james-age (cdr x))
   What remains is the first element in the list, which is (car x),
and you should handle it.

    For sure we know that, after the 2nd line x is a non-nil
list (because if it were nil, it would be handled in the 2nd line)
So, (car x) will be a pair like (jordan 17) or (pat 45)
There are 2 cases the car of (car x) is either jordan or not.
   case 1:  (car (car x)) is jordan
   case 2:  (car (car x)) is not jordan

You can handle case 1 in the 3rd line as:

(defun james-age (x)
   (cond ( (null x)  nil )
         ( (equal (car (car x)) 'jordan)  ... )
          ...
                ))

   What should you do? You should include the pair (car x)
somehow in the result. The rest of the list will be handled
by (james-age (cdr x))

   (cdr x)   ((peter 38) (james 12) (patric 32))

  and (james-age (cdr x)) will return  ((james 12)) for YOU.
(Don't think about how it will return it. Suppose it will
  work correctly. Only concentrate what it will RETURN)

 If you try to include (car x)  [let say it is (jordan 27)]

using  (list (car x) (james-age (cdr x)))

   ( (jordan 27) ((james 12)) )

will be returned. This is not what you want. So, list is the WRONG
function to use. Use cons instead!

   (cons (car x) (james-age (cdr x)))

will return ( (jordan 27) (james 12) )  which preserves the format
you want as return value.

So, you complete case 1 as:

(defun james-age (x)
   (cond ( (null x)  nil )
         ( (equal (car (car x)) 'jordan)  
              (cons (car x) (james-age (cdr x))) )
         ( t  ...
                ))

  case 2 is the remaining part: it is like saying else
If it is equal to jordan ..case1...  else ...case2...
So, I put t in the test-expr to always succeed.

What should we return? Should we include (car x) in the result?
It's a pair like (pat 48), so get rid of it. Only return
the value from the rest of the list.

(defun james-age (x)
   (cond ( (null x)  nil )
         ( (equal (car (car x)) 'jordan)  
              (cons (car x) (james-age (cdr x))) )
         ( t  (james-age (cdr x)) )
                ))

   Now you completed the definition and your assumption
that somebody had written a james-age function for you
turns out to be a self fulfilling prophecy, and you find out that
that someone was in fact you! 

hope this helps,

  alex
From: Alex Aris
Subject: Re: CAR/CDR Recursion
Date: 
Message-ID: <9r84vd$lmn$1@hecate.umd.edu>
ab talebi (············@yahoo.com) wrote:
: (defun james-age (x)
:   (cond ((equal (car x) 'james) x)
:         ((null x) nil)
:         (t (list (james-age (car x))
:                  (james-age (cdr x))))))


: I have written this car/cdr recursion, but I don't get it to work and
: I don't know why.

first of all, you check 'james with car.
(car x) will return (james 27) if x is the list below.
So, the correct way, would be (car (car x)) or (caar x)

But this is not enough. Let's see:
After this modification, your defn becomes:

 (defun james-age (x)
   (cond ((equal (caar x) 'james) x)
         ((null x) nil)
         (t (list (james-age (car x))
                  (james-age (cdr x))))))

I don't know what you meant in the 4th line.
(james-age (car x)) will cause to apply car 
to a non-list value because you will call james-age with 
(james 27) as argument which doesn't have the same format as
you intended at first.


: The idea is that this will take a nested list like:
: ((james 27) (peter 38) (james 12) (patric 32)) 
: and returns all the james and their ages:
: ((james 27) (james 12))

When you write a recursive function, you first 
find a base case. It;s usually the smallest valid list.
And you may have () as the smalles. So, you write the
function handling base case first. 
What should it return?

> (james-age '())
NIL

right? because there are no pairs at all. So,

(defun james-age (x)
   (cond ( (null x)  nil )
          ...
                ))

   Now, you can consider the recursive case.
The trick is that you assume that somebody else has already
written james-age and it's READY for YOU there. You can use it freely
in your definition to solve a smaller problem.

    A smaller problem will be a smaller list, like
the cdr of the list, for instance.

    So, the recursive call will look like 
(james-age (cdr x))
   What remains is the first element in the list, which is (car x),
and you should handle it.

    For sure we know that, after the 2nd line x is a non-nil
list (because if it were nil, it would be handled in the 2nd line)
So, (car x) will be a pair like (james 17) or (pat 45)
There are 2 cases the car of (car x) is either james or not.
   case 1:  (car (car x)) is james
   case 2:  (car (car x)) is not james

You can handle case 1 in the 3rd line as:

(defun james-age (x)
   (cond ( (null x)  nil )
         ( (equal (car (car x)) 'james)  ... )
          ...
                ))

   What should you do? You should include the pair (car x)
somehow in the result. The rest of the list will be handled
by (james-age (cdr x))

   (cdr x)   ((peter 38) (james 12) (patric 32))

  and (james-age (cdr x)) will return  ((james 12)) for YOU.
(Don't think about how it will return it. Suppose it will
  work correctly. Only concentrate what it will RETURN)

 If you try to include (car x)  [let say it is (james 27)]

using  (list (car x) (james-age (cdr x)))

   ( (james 27) ((james 12)) )

will be returned. This is not what you want. So, list is the WRONG
function to use. Use cons instead!

   (cons (car x) (james-age (cdr x)))

will return ( (james 27) (james 12) )  which preserves the format
you want as return value.

So, you complete case 1 as:

(defun james-age (x)
   (cond ( (null x)  nil )
         ( (equal (car (car x)) 'james)  
              (cons (car x) (james-age (cdr x))) )
         ( t  ...
                ))

  case 2 is the remaining part: it is like saying else
If it is equal to james ..case1...  else ...case2...
So, I put t in the test-expr to always succeed.

What should we return? Should we include (car x) in the result?
It's a pair like (pat 48), so get rid of it. Only return
the value from the rest of the list.

(defun james-age (x)
   (cond ( (null x)  nil )
         ( (equal (car (car x)) 'james)  
              (cons (car x) (james-age (cdr x))) )
         ( t  (james-age (cdr x)) )
                ))

   Now you completed the definition and your assumption
that somebody had written a james-age function for you
turns out to be a self fulfilling prophecy, and you find out that
that someone was in fact you! 

hope this helps,

  alex