From: Valentin Hans
Subject: Lisp newbie needs help
Date: 
Message-ID: <293e4881.0409300626.21837454@posting.google.com>
Hello,
regarding Lisp programming I am an absolute newbie. I just started
learning Common Lisp a few days ago and I have got a problem. I wanted
to write a small game and my code contains the following function that
throws a dice until the thrown number  is a "1". However, CLISP (I am
using version 2.33) never prints "One thrown". Could anyone please
figure out why this is so?

(defun my-test (&aux (sum 0)) 
	(do () (nil nil)
		(let ((number (+ (random 6) 1)))
			(if (= number 1)
				(format t "~&One thrown." (setf sum 0) (return)))
			(format t "~&~D thrown. Sum: ~D" number (incf sum number)))))

(I know that "sum" is quite useless here; the function above is just a
stripped down version of the function I am using)

From: Daniel Lowe
Subject: Re: Lisp newbie needs help
Date: 
Message-ID: <41acafc6.0409301050.56558f9b@posting.google.com>
·····@web.de (Valentin Hans) wrote in message news:<····························@posting.google.com>...
> Hello,
> regarding Lisp programming I am an absolute newbie. I just started
> learning Common Lisp a few days ago and I have got a problem. I wanted
> to write a small game and my code contains the following function that
> throws a dice until the thrown number  is a "1". However, CLISP (I am
> using version 2.33) never prints "One thrown". Could anyone please
> figure out why this is so?
> 
> (defun my-test (&aux (sum 0)) 
> 	(do () (nil nil)
> 		(let ((number (+ (random 6) 1)))
> 			(if (= number 1)
> 				(format t "~&One thrown." (setf sum 0) (return)))
> 			(format t "~&~D thrown. Sum: ~D" number (incf sum number)))))

Look at the expression:
   (format t "~&One thrown." (setf sum 0) (return))

What's going on there?  Each argument is evaluated and then all of
them are passed to the format function.  When the (return) expression
is evaluated, it returns, and the format function never has a chance
to execute.

As a comparison, here's how I'd write it:

(defun my-test ()
   (do* ((number (1+ (random 6)) (1+ (random 6)))
         (sum number (+ sum number)))
        ((= number 1))
       (format t "~&~D thrown. Sum: ~D" number sum))
   (format t "~&One thrown."))

or even:

(defun my-test ()
   (loop for number = (1+ (random 6))
         as sum = number then (+ sum number)
         until (= number 1)
         do (format t "~&~D thrown. Sum: ~D" number sum)
         finally (format t "~&One thrown.")))
From: Valentin Hans
Subject: Re: Lisp newbie needs help
Date: 
Message-ID: <293e4881.0410020224.7ae144c@posting.google.com>
Thanks indeed for your help. Now I have got lots of things to ponder on ;-)

Vali
From: William Bland
Subject: Re: Lisp newbie needs help
Date: 
Message-ID: <pan.2004.09.30.14.37.54.362740@abstractnonsense.com>
On Thu, 30 Sep 2004 07:26:30 -0700, Valentin Hans wrote:

> Hello,
> regarding Lisp programming I am an absolute newbie. I just started
> learning Common Lisp a few days ago and I have got a problem. I wanted
> to write a small game and my code contains the following function that
> throws a dice until the thrown number  is a "1". However, CLISP (I am
> using version 2.33) never prints "One thrown". Could anyone please
> figure out why this is so?
> 
> (defun my-test (&aux (sum 0)) 
> 	(do () (nil nil)
> 		(let ((number (+ (random 6) 1)))
> 			(if (= number 1)
> 				(format t "~&One thrown." (setf sum 0) (return)))
> 			(format t "~&~D thrown. Sum: ~D" number (incf sum number)))))

You have an unused argument to the format function.  I couldn't find
anything in the HyperSpec that says what happens in such a case, but CMUCL
complains about it.

I rewrote your IF as a WHEN:

(when (= number 1)
  (format t "~&One thrown." (setf sum 0))
  (return))

The function now works for me.  As an aside, I never use &aux.  I prefer
let, or let* instead.

Hope that helps.

Cheers,
	Bill.
-- 
Dr. William Bland.
It would not be too unfair to any language to refer to Java as a
stripped down Lisp or Smalltalk with a C syntax.   (Ken Anderson).
From: William Bland
Subject: Re: Lisp newbie needs help
Date: 
Message-ID: <pan.2004.09.30.14.46.07.62313@abstractnonsense.com>
On Thu, 30 Sep 2004 14:46:19 +0000, William Bland wrote:

> You have an unused argument to the format function.

Oops, you have *two* unused arguments to FORMAT.  Rewrite as:

(when (= number 1)
  (format t "~&One thrown.")
  (setf sum 0)
  (return))

Of course there's not much point in resetting sum to 0 here, but you said
it was part of a bigger function so I've left it in.

Cheers,
	Bill.
-- 
Dr. William Bland.
It would not be too unfair to any language to refer to Java as a
stripped down Lisp or Smalltalk with a C syntax.   (Ken Anderson).
From: Kalle Olavi Niemitalo
Subject: Re: Lisp newbie needs help
Date: 
Message-ID: <87mzz4l4mp.fsf@Astalo.kon.iki.fi>
William Bland <·······@abstractnonsense.com> writes:

> You have an unused argument to the format function.  I couldn't find 
> anything in the HyperSpec that says what happens in such a case, but 
> CMUCL complains about it.

See CLHS section 22.3.10.2: Missing and Additional FORMAT Arguments.  
Extra arguments are to be ignored.
From: Max-Gerd Rettzlaff
Subject: Re: Lisp newbie needs help
Date: 
Message-ID: <cjhbu8$8qu$1@news2.rz.uni-karlsruhe.de>
Hi

Valentin Hans <·····@web.de> wrote:
> (defun my-test (&aux (sum 0)) 
> 	(do () (nil nil)
> 		(let ((number (+ (random 6) 1)))
> 			(if (= number 1)
> 				(format t "~&One thrown." (setf sum 0) (return)))
> 			(format t "~&~D thrown. Sum: ~D" number (incf sum number)))))

You seem to have forgotten to close the parenthesis direct after the
string "~&One thrown." and added it later at the wrong place. As you
have written it (setf sum 0) and (return) are (unused) parameters to
format. As format is a function its arguments are evaluated first;
when return is called the control is immediately returned from the
implicit block of the do-construct, and therefore the function format 
itself is never executed (in this form).

A corrected version could look like this:

(defun my-test (&aux (sum 0))
  (do () (nil nil)
    (let ((number (+ (random 6) 1)))
      (if (= number 1)
          (progn
            (format t "~&One thrown.")
            (setf sum 0)
            (return)))
      (format t "~&~D thrown. Sum: ~D" number (incf sum number)))))

Of course you could replace the (if .. (progn ..)) by a when-construct
as it has no else-part:

(defun my-test (&aux (sum 0))
  (do () (nil nil)
    (let ((number (+ (random 6) 1)))
      (when (= number 1)
        (format t "~&One thrown.")
        (setf sum 0)
        (return))
      (format t "~&~D thrown. Sum: ~D" number (incf sum number)))))

But this cries for another rewrite as you have nil as first argument
to the do-construct but you use these ugly &aux-parameters and another
(let ..). In addition to this the if/when+return can be written as the
second parameter to the do-expression:

(defun my-test ()
  (do ((sum 0)
       (number (+ (random 6) 1)
               (+ (random 6) 1)))
      ((= number 1) (format t "~&One thrown.")
                    (setf sum 0))
    (format t "~&~D thrown. Sum: ~D" number (incf sum number))))

I hope that helps, and that my explanations are indeed correct.

Bye, Max

-- 
Max-Gerd Retzlaff  <··········@bl0rg.net>