From: Andrew Burton
Subject: Newbie question
Date: 
Message-ID: <20030420021310.18816.00000349@mb-m05.aol.com>
I'm reading an article(1) on the history of Lisp, and they were talking about
when Interlisp started using...

(+ 1 2 3 4)

...instead of...

(+ 1 (+ 2 (+ 3 4)))

...in the dialect.  Now, I thought it'd be fun to see if I could figure my way
through a function that would kind of do the same thing, only adding two
numbers every loop and passing a shrinking list everytime.  Unfortunately, I've
hit a snag.  CDR keeps embedding a list into a list, so what I CAR the list, I
get NIL.  I'm "prototyping" this piece of code, just to get a bit more exposure
out CDR and recursion.  Here's the code:

;;
(defun stripper (&rest z) (if
	(equal (car z) nil) (format t "End")
	(list
		(format t "~D~%" (car z))
		(setq z (cdr z))
		(stripper z))))
;;

Here's what I get when I run it through clisp on my Windows machine:

81. Break [88]> (stripper 1 2 3)
1
(2 3)
End
(NIL (2 3) NIL (NIL NIL NIL NIL))
81. Break [88]>

Here's my question: Is there a way to CDR the list without it sticking a list
into a list?  I get the feeling I need to use CONS, but for the life of me I
can't figure out how.  I'd just use something like REST, which I think is a
command, but I'd like to see if this can be pulled off without going much past
CAR, CDR, +, and very basic functions.  I hope it's okay to ask this kind of
thing here, if not just ignore me and I won't post stupid code bits like this
again.  Thanks in advance!

---

1. http://www.dreamsongs.com/NewFiles/Hopl2.pdf

Andrew Burton -- tuglyraisin at aol dot com
Felecia Station on Harvestgain -- http://www.darkbeast.com/
Jipi: Don't believe everything the Net tells you.
Chip: I agree with this. My inputs are not to be trusted.
CROW: Quick, save the Robot Ashley!

From: Kalle Olavi Niemitalo
Subject: Re: Newbie question
Date: 
Message-ID: <87of31bpqk.fsf@Astalo.kon.iki.fi>
···········@aol.commune (Andrew Burton) writes:

> (defun stripper (&rest z) (if
> 	(equal (car z) nil) (format t "End")
> 	(list
> 		(format t "~D~%" (car z))
> 		(setq z (cdr z))
> 		(stripper z))))

Your problem seems to be that CDR returns a list, and then the
recursive call passes the whole list as one argument, rather than
each element as a separate argument.  Calls of the form (stripper z)
always pass the value of Z as only one argument; you can't change
this by using a different function instead of CDR.  You need to
change the call itself.  To pass the elements of a list as separate
arguments, use APPLY:

  (apply #'stripper z)

You should also change (equal (car z) nil) to (null z).  The
first one primarily checks whether whether the first element of
the list is NIL, and matches empty lists due to a quirk of the
language; the latter explicitly checks whether the list is empty.

> I'd just use something like REST, which I think is a command,
> but I'd like to see if this can be pulled off without going
> much past CAR, CDR, +, and very basic functions.

REST is equivalent to CDR; whenever a program calls REST, it
could instead call CDR and get the same result.  So if you can't
use CDR, then REST won't help.
From: Andrew Burton
Subject: Re: Newbie question
Date: 
Message-ID: <20030420132652.18816.00000363@mb-m05.aol.com>
> Your problem seems to be that CDR returns a list, and then the
> recursive call passes the whole list as one argument, rather than
> each element as a separate argument.

That was my problem, the BIG problem.  (apply #'stripper z) worked exactly like
I needed it to do.  Thank you.  I had to skip using (null z), though, since I
wasn't looking for a fully empty list but a list with only one element.  (null)
will come in handy in future, I've no doubt, thanks for letting me in on it. :)
 Here's the code I was ultimately working toward, which wouldn't have been if
not for you and a very nice emailer.  Thanks.

;;
(defun adder (&rest z)
	(if (equal (cdr z) nil)
		(format t "~D~%" (car z))
		(list	(setq y (+ (car z) (car (cdr z))))
			(setq z (cddr z))
			(apply #'adder y z))))
;;

Andrew Burton -- tuglyraisin at aol dot com
Felecia Station on Harvestgain -- http://www.darkbeast.com/
Jipi: Don't believe everything the Net tells you.
Chip: I agree with this. My inputs are not to be trusted.
CROW: Quick, save the Robot Ashley!
From: Kalle Olavi Niemitalo
Subject: Re: Newbie question
Date: 
Message-ID: <87u1cthv6q.fsf@Astalo.kon.iki.fi>
···········@aol.commune (Andrew Burton) writes:

> I had to skip using (null z), though, since I wasn't looking
> for a fully empty list but a list with only one element.

Then you can use (null (cdr z)).  :-)  It's equivalent to your
(equal (cdr z) nil).

> (defun adder (&rest z)
> 	(if (equal (cdr z) nil)
> 		(format t "~D~%" (car z))
> 		(list	(setq y (+ (car z) (car (cdr z))))
> 			(setq z (cddr z))
> 			(apply #'adder y z))))

This returns quite a list; is that necessary?
From: Andrew Burton
Subject: Re: Newbie question
Date: 
Message-ID: <20030420234304.18889.00000424@mb-m03.aol.com>
Which list?  The list of numbers being added, or all those NIL's at the end? 
If you mean the latter, I'm trying to figure out how to get rid of those.

Andrew Burton -- tuglyraisin at aol dot com
Felecia Station on Harvestgain -- http://www.darkbeast.com/
Jipi: Don't believe everything the Net tells you.
Chip: I agree with this. My inputs are not to be trusted.
CROW: Quick, save the Robot Ashley!
From: Brian Palmer
Subject: Re: Newbie question
Date: 
Message-ID: <0why924idla.fsf@rescomp.Stanford.EDU>
···········@aol.commune (Andrew Burton) writes:

> Which list?  The list of numbers being added, or all those NIL's at
> the end? If you mean the latter, I'm trying to figure out how to get
> rid of those.

Could you please include some context when you respond to posts? (A
snippet of the post you're responding to, as I've done here). 

There's problems with the last code you posted in that y is a free
variable that you're writing to; you probably want to wrap it within a
let form. But,more importantly, you're passing your arguments all in
z, and then most of the effort in the function goes to destructuring
that list. Why not do a function with prototype like 

(defun adder (current-sum addands) 
        ;; Fill in code here 
)

The recursion works a lot more naturally, and if you want you can
create a wrapper function
(defun wrapper (&rest r)
        (adder 0 r))
so you can call (wrapper 1 2 5)

-- 
If you want divine justice, die.
                  -- Nick Seldon 
From: Fred Gilham
Subject: Re: Newbie question
Date: 
Message-ID: <u73ckb6d2w.fsf@snapdragon.csl.sri.com>
···········@aol.commune (Andrew Burton) writes:
> Which list?  The list of numbers being added, or all those NIL's at
> the end?  If you mean the latter, I'm trying to figure out how to
> get rid of those.

Take a look at the following.  Seems to do what you want.

(defun adder2 (&rest z)
  (if (eq (cdr z) nil)
    (format t "~D~%" (car z))
    (let ((y (+ (car z) (car (cdr z))))
	  (z (cddr z)))
      (apply #'adder2 y z))))

-- 
Fred Gilham                                        ······@csl.sri.com
The rage of dance and style that swept the country in the late '70s
crumbled from serious backlash as disco freaks seemed to finally wake
up and realize what they were wearing.  -- Michael Okwu
From: Kalle Olavi Niemitalo
Subject: Re: Newbie question
Date: 
Message-ID: <87he8rss5t.fsf@Astalo.kon.iki.fi>
Fred Gilham <······@snapdragon.csl.sri.com> writes:

>     (let ((y (+ (car z) (car (cdr z))))
> 	  (z (cddr z)))
>       (apply #'adder2 y z))

Or (apply #'adder2 (+ (pop z) (pop z)) z), if you don't restrict
yourself to basic functions.
From: Andrew Burton
Subject: Re: Newbie question
Date: 
Message-ID: <20030421170414.18950.00000193@mb-m26.aol.com>
> Or (apply #'adder2 (+ (pop z) (pop z)) z), 
> if you don't restrict yourself to basic 
> functions.

Or (+ x y z) if you want to do it like it is. ;-)  I was just trying to see how
something like + might be written with a basic set of commands if you were only
allowed to enter two numbers to be added at a time.  Pointless, sure, but
pretty educational for me.



Andrew Burton -- tuglyraisin at aol dot com
Felecia Station on Harvestgain -- http://www.darkbeast.com/
Jipi: Don't believe everything the Net tells you.
Chip: I agree with this. My inputs are not to be trusted.
CROW: Quick, save the Robot Ashley!
From: Matthew Danish
Subject: Re: Newbie question
Date: 
Message-ID: <20030421181618.P13181@lain.cheme.cmu.edu>
On Mon, Apr 21, 2003 at 09:04:14PM +0000, Andrew Burton wrote:
> > Or (apply #'adder2 (+ (pop z) (pop z)) z), if you don't restrict
> > yourself to basic functions.
> 
> Or (+ x y z) if you want to do it like it is. ;-)  I was just trying
> to see how something like + might be written with a basic set of
> commands if you were only allowed to enter two numbers to be added at
> a time.  Pointless, sure, but pretty educational for me.

REDUCE.

(defun add2 (x y)
  (+ x y))

(defun add (&rest args)
  (reduce #'add2 args :initial-value 0))


To accomplish this without using REDUCE, consider the following
function:

(defun add (&rest args)
  (cond ((null args)
	 ;; Calling ADD with no arguments results in the additive
	 ;; identity value:
         0)
        ((consp args)
	 ;; Now we know that we have been given a CONS, and we will
	 ;; assume that it is a proper list (one that ends in NIL).
	 ;; We will further assume that (FIRST ARGS) holds a number.
	 ;; It should be a fairly simple deduction to realize that
	 ;; adding (FIRST ARGS) to the result of (APPLY #'ADD (REST ARGS))
	 ;; will give us the sum of the whole list ARGS.
	 ;; We assume, for the time being, that we can correctly
	 ;; implement the ADD function so that this is true.
	 ;; Mathematicians call this assumption the "inductive hypothesis", 
	 ;; in case you were wondering.
         (add2 (first args)
               (apply #'add (rest args))))))

;; Remember, APPLY will act as so:
;; (F 1 2 3) <==> (APPLY #'F '(1 2 3)) <==> (APPLY #'F 1 '(2 3)) ...

Here is a more efficient implementation (other than using REDUCE) for 
you to figure out:

(defun add (&rest args)
  (cond ((null args)
         0)
        ((consp args)
         (if (null (rest args))
           (first args)
           (apply #'add 
                  (add2 (first args)
                        (second args))
                  (cddr args))))))
	
I purposely constructed this function so that the recursive application
of ADD would be the last thing done in each execution of the function
body (each one which reached the "inductive hypothesis" in any case).

On a final note, I noted that you used the function LIST in a few places
where it did not seem appropriate, in your original example.  You should
keep in mind precisely what that function does--it constructs a list
from its arguments, and returns it.  I think it is not what you meant to
use.

-- 
; Matthew Danish <·······@andrew.cmu.edu>
; OpenPGP public key: C24B6010 on keyring.debian.org
; Signed or encrypted mail welcome.
; "There is no dark side of the moon really; matter of fact, it's all dark."
From: Andrew Burton
Subject: Re: Newbie question
Date: 
Message-ID: <20030421231625.18839.00000226@mb-m23.aol.com>
> On a final note, I noted that you used the function LIST in a few places
> where it did not seem appropriate, in your original example.  You should
> keep in mind precisely what that function does--it constructs a list
> from its arguments, and returns it.  I think it is not what you meant to
> use.

Yeah, I agree I do misuse the LIST function.  I've never sat down and found the
clisp equivalent to Scheme's BEGIN function.  I discovered LIST would do
something equivalent, and much to my embaracement, never looked back.  Now,
though, that I know for sure it's the wrong way to do things, I'll find the
proper way.  Thanks.

Andrew Burton -- tuglyraisin at aol dot com
Felecia Station on Harvestgain -- http://www.darkbeast.com/
Jipi: Don't believe everything the Net tells you.
Chip: I agree with this. My inputs are not to be trusted.
CROW: Quick, save the Robot Ashley!
From: Andrew Burton
Subject: Re: Newbie question
Date: 
Message-ID: <20030422000018.18839.00000228@mb-m23.aol.com>
>> On a final note, I noted that you used the function LIST in a few places
>> where it did not seem appropriate, in your original example

> Now, though, that I know for sure it's the wrong way to do things, I'll find
> the proper way.  Thanks.

I figured out what I was doing wrong.  Encapsulation is still something I've
got to improve on. :)

;;
(defun adder (&rest z)
	(if (equal (cdr z) nil)
		(format t "~D~%" (car z))
		(apply #'adder
			(+ (car z) (car (cdr z)))
			(cddr z))))
;;



Andrew Burton -- tuglyraisin at aol dot com
Felecia Station on Harvestgain -- http://www.darkbeast.com/
Jipi: Don't believe everything the Net tells you.
Chip: I agree with this. My inputs are not to be trusted.
CROW: Quick, save the Robot Ashley!
From: Matthew Danish
Subject: Re: Newbie question
Date: 
Message-ID: <20030422004026.Q13181@lain.cheme.cmu.edu>
On Tue, Apr 22, 2003 at 04:00:18AM +0000, Andrew Burton wrote:
> >> On a final note, I noted that you used the function LIST in a few places
> >> where it did not seem appropriate, in your original example
> 
> > Now, though, that I know for sure it's the wrong way to do things, I'll find
> > the proper way.  Thanks.
> 
> I figured out what I was doing wrong.  Encapsulation is still something I've
> got to improve on. :)
> 
> ;;
> (defun adder (&rest z)
> 	(if (equal (cdr z) nil)
> 		(format t "~D~%" (car z))
> 		(apply #'adder
> 			(+ (car z) (car (cdr z)))
> 			(cddr z))))
> ;;

1. See PROGN

2. Yikes, stop using FORMAT so indiscriminately!  There is a difference
between printing out the result and returning it.  The REPL will print
out the return values of any expression that you evaluate, so you don't
have to do it explicitly.

What if you wanted to do (* 2 (adder 1 2 3)), after all?

-- 
; Matthew Danish <·······@andrew.cmu.edu>
; OpenPGP public key: C24B6010 on keyring.debian.org
; Signed or encrypted mail welcome.
; "There is no dark side of the moon really; matter of fact, it's all dark."
From: Matthew Danish
Subject: Re: Newbie question
Date: 
Message-ID: <20030422004228.R13181@lain.cheme.cmu.edu>
On Tue, Apr 22, 2003 at 04:00:18AM +0000, Andrew Burton wrote:
> 	(if (equal (cdr z) nil)

Oh yeah, and (null (rest z)) or at least (null (cdr z)) is much easier
to read than the above, and equivalent.

(And your function will return an incorrect result when supplied with 0
arguments, BTW).

-- 
; Matthew Danish <·······@andrew.cmu.edu>
; OpenPGP public key: C24B6010 on keyring.debian.org
; Signed or encrypted mail welcome.
; "There is no dark side of the moon really; matter of fact, it's all dark."
From: Andrew Burton
Subject: Re: Newbie question
Date: 
Message-ID: <20030422082428.18862.00000782@mb-m05.aol.com>
> (And your function will return an incorrect 
> result when supplied with 0 arguments, 
> BTW).

Really?  When I type in (adder) it gives me NIL as a result.  I'll have to see
if I can squeeze &optional somewhere in there, that might help.

Andrew Burton -- tuglyraisin at aol dot com
Felecia Station on Harvestgain -- http://www.darkbeast.com/
Jipi: Don't believe everything the Net tells you.
Chip: I agree with this. My inputs are not to be trusted.
CROW: Quick, save the Robot Ashley!
From: Jeremy Yallop
Subject: Re: Newbie question
Date: 
Message-ID: <b83egl$5o6bq$1@ID-114079.news.dfncis.de>
Andrew Burton wrote:
>> (And your function will return an incorrect 
>> result when supplied with 0 arguments, 
>> BTW).
> 
> Really?  When I type in (adder) it gives me NIL as a result.

Yes, it should return 0, as (+) does.

> I'll have to see if I can squeeze &optional somewhere in there, that
> might help.

You don't need &optional.  OR will do fine.

  (defun adder (&rest z)
    (if (null (cdr z))
        (or (car z) 0)
      (apply #'adder
             (+ (car z) (cadr z))
             (cddr z))))

Jeremy.
From: Andrew Burton
Subject: Re: Newbie question
Date: 
Message-ID: <20030422095854.18808.00000412@mb-m19.aol.com>
> (or (car z) 0)

Cool.  Thanks!

Andrew Burton -- tuglyraisin at aol dot com
Felecia Station on Harvestgain -- http://www.darkbeast.com/
Jipi: Don't believe everything the Net tells you.
Chip: I agree with this. My inputs are not to be trusted.
CROW: Quick, save the Robot Ashley!
From: Marco Antoniotti
Subject: Re: Newbie question
Date: 
Message-ID: <zHcpa.14$L4.1800@typhoon.nyu.edu>
Andrew Burton wrote:

> >On a final note, I noted that you used the function LIST in a few places
> >where it did not seem appropriate, in your original example.  You should
> >keep in mind precisely what that function does--it constructs a list
> >from its arguments, and returns it.  I think it is not what you meant to
> >use.
>
>
> Yeah, I agree I do misuse the LIST function.  I've never sat down and 
> found the
> clisp equivalent to Scheme's BEGIN function. 

You just need to ask.  CL has PROGN.

>  I discovered LIST would do
> something equivalent, and much to my embaracement, never looked back. 
>  Now,
> though, that I know for sure it's the wrong way to do things, I'll 
> find the
> proper way.  Thanks.


You are welcome

--
Marco Antoniotti
From: Kalle Olavi Niemitalo
Subject: Re: Newbie question
Date: 
Message-ID: <87d6jg72u1.fsf@Astalo.kon.iki.fi>
···········@aol.commune (Andrew Burton) writes:

> Which list?

I mean that the function writes the sum to standard output, and
returns a three-element list where the first two elements are
numbers and the third element can again be a three-element list.
Do you actually need that list for anything; would it be OK to
return the sum instead?
From: Andrew Burton
Subject: Re: Newbie question
Date: 
Message-ID: <20030421165800.18950.00000192@mb-m26.aol.com>
> I mean that the function writes the sum 
> to standard output, and returns a 
> three-element list where the first two 
> elements are numbers and the third 
> element can again be a three-element 
> list.

No, I don't need the (format t "~D~% (car z)) part.  I had just added that to
see how it was processing the CDR's in the loop.  It never got taken out, and
my original purpose for this was just to end the thing with a single number,
the sum of all input numbers.

As for the element list, and I may be totally misunderstanding what you mean by
"element list," I just don't know how to get rid of it?  If you could show me
something to add that would prevent it from being displayed, I would get rid of
it in a heart beat.


> Do you actually need that list for anything;
> would it be OK toreturn the sum instead?

Again, the purpose was just to return the sum.  The first list is just my
forgetting to remove the (format), and all those NIL's after the sum are there
simply because I lack the knowledge to get rid of them.

Andrew Burton -- tuglyraisin at aol dot com
Felecia Station on Harvestgain -- http://www.darkbeast.com/
Jipi: Don't believe everything the Net tells you.
Chip: I agree with this. My inputs are not to be trusted.
CROW: Quick, save the Robot Ashley!
From: Kalle Olavi Niemitalo
Subject: Re: Newbie question
Date: 
Message-ID: <878yu37cdo.fsf@Astalo.kon.iki.fi>
···········@aol.commune (Andrew Burton) writes:

> I may be totally misunderstanding what you mean by "element list,"

By "three-element list", I mean a list that contains three elements.