From: ·········@aol.com
Subject: i cant make a loop that exits when a conditon is met
Date: 
Message-ID: <1139005945.182413.280540@g47g2000cwa.googlegroups.com>
in scheme i would do this

(define *score* 0)
(define (quiz)
  (set! *score* 0)
  (display "press enter to start ")
  (let ((exit (read-line)))
    (if (equal? exit "foo bar baz")
	(display "")
	(begin
	  (display "who is the richest man? ")
	  (let ((q1 (read-line)))
	    (if (equal? q1 "bill gates")
		(begin (display "Corect\n")
		       (set! *score* (+ *score* 100))
		       (display *score*)
		       (newline))
		(begin (display "incorect\n")
		       (set! *score* (- *score* 100))
		       (display *score*)
		       (newline))))
	  (quiz)))))

how would i do the same thing in common lisp

From: David Sletten
Subject: Re: i cant make a loop that exits when a conditon is met
Date: 
Message-ID: <OGREf.5230$Z3.4789@tornado.socal.rr.com>
·········@aol.com wrote:

> in scheme i would do this
> 
> (define *score* 0)
> (define (quiz)
>   (set! *score* 0)
>   (display "press enter to start ")
>   (let ((exit (read-line)))
>     (if (equal? exit "foo bar baz")
> 	(display "")
> 	(begin
> 	  (display "who is the richest man? ")
> 	  (let ((q1 (read-line)))
> 	    (if (equal? q1 "bill gates")
> 		(begin (display "Corect\n")
> 		       (set! *score* (+ *score* 100))
> 		       (display *score*)
> 		       (newline))
> 		(begin (display "incorect\n")
> 		       (set! *score* (- *score* 100))
> 		       (display *score*)
> 		       (newline))))
> 	  (quiz)))))
> 
> how would i do the same thing in common lisp
> 

It's easy, you just made a few typos:
(defvar *score* 0)
(defun quiz ()
   (format t "Press enter to start ")
   (let ((exit (read-line)))
     (unless (equal exit "foo bar baz")
       (format t "Who is the richest man? ")
       (let ((q1 (read-line)))
         (cond ((equalp q1 "Bill Gates")
                (incf *score* 100)
                (format t "Correct~%"))
               (t (decf *score* 100)
                  (format t "Incorrect~%")))
         (format t "~D~%" *score*))
         (quiz))))

(Notice that you clobber the score on each recursive call of QUIZ.)

Here's a better version:
(defun quiz ()
   (let ((score 0))
     (labels ((query ()
                (format t "Press enter to start ")
                (let ((exit (read-line)))
                  (unless (equal exit "foo bar baz")
                    (format t "Who is the richest man? ")
                    (let ((q1 (read-line)))
                      (cond ((equalp q1 "Bill Gates")
                             (incf score 100)
                             (format t "Correct~%"))
                            (t (decf score 100)
                               (format t "Incorrect~%")))
                      (format t "~D~%" score))
                    (query)))) )
       (query))))

Here we no longer need a global variable. The outer function QUIZ also 
properly initializes the score while QUERY updates its value on each round.

Of course, since you asked about loops you are probably interested in these:
http://www.lispworks.com/documentation/HyperSpec/Body/m_do_do.htm
http://www.lispworks.com/documentation/HyperSpec/Body/m_loop.htm
http://www.lispworks.com/documentation/HyperSpec/Body/s_block.htm
http://www.lispworks.com/documentation/HyperSpec/Body/s_ret_fr.htm

Aloha,
David Sletten
From: ·········@aol.com
Subject: Re: i cant make a loop that exits when a conditon is met
Date: 
Message-ID: <1139016131.440675.284050@g47g2000cwa.googlegroups.com>
for user input i use this user defined function

(defun prompt-read (prompt)
  (format *query-io* "~a" prompt)
  (force-output *query-io*)
  (read-line *query-io*))
From: ·········@aol.com
Subject: Re: i cant make a loop that exits when a conditon is met
Date: 
Message-ID: <1139016251.791106.287590@g44g2000cwa.googlegroups.com>
does CL have tail-call-optamazation
From: Pascal Bourguignon
Subject: Re: i cant make a loop that exits when a conditon is met
Date: 
Message-ID: <87lkwr99z5.fsf@thalassa.informatimago.com>
·········@aol.com writes:

> does CL have tail-call-optamazation

CL does not.  Most CL implementations do have it.

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

HEALTH WARNING: Care should be taken when lifting this product,
since its mass, and thus its weight, is dependent on its velocity
relative to the user.
From: Gareth McCaughan
Subject: Re: i cant make a loop that exits when a conditon is met
Date: 
Message-ID: <87wtgb7toj.fsf@g.mccaughan.ntlworld.com>
Pascal Bourguignon wrote:

> ·········@aol.com writes:
> 
>> does CL have tail-call-optamazation
> 
> CL does not.  Most CL implementations do have it.

To clarify:

  - The standard that defines CL doesn't require any sort
    of tail-call optimization.

  - Just about every CL implementation (maybe all, without
    exception?) optimizes some tail calls in some situations.

  - I don't think any CL implementation optimizes them
    as fully as the Scheme standard requires all conforming
    Scheme implementations to do.

The following ...

  | (defun wibble (n)
  |   (when (zerop (mod n 1000000)) (format t "~&~A~%" (/ n 1000000)))
  |   (wibble (1+ n)))
  | 
  | (compile 'wibble)
  | 
  | (wibble 0)

runs happily and quickly up to at least n=140 on my
machine under CMU CL, which is enough to convince me
that it's doing TCO. Under CLISP (which doesn't compile
to native code) it's somewhat slower, but again it
gets far enough that I'm sure it's doing TCO. (Also,
the CLISP process isn't growing in size.) Those are
the only Common Lisps I happen to have installed
at present.

(By "doing TCO" I mean "converting tail recursion
into a non-allocating branch, for this function
on this occasion", not e.g. "turning all tail calls,
without exception, into branches".)

-- 
Gareth McCaughan
.sig under construc
From: GB
Subject: Re: i cant make a loop that exits when a conditon is met
Date: 
Message-ID: <LwZEf.85168$0G.23416@dukeread10>
Gareth McCaughan wrote:
> The following ...
> 
>   | (defun wibble (n)
>   |   (when (zerop (mod n 1000000)) (format t "~&~A~%" (/ n 1000000)))
>   |   (wibble (1+ n)))
>   | 
>   | (compile 'wibble)
>   | 
>   | (wibble 0)
> 
> runs happily and quickly up to at least n=140 on my
> machine under CMU CL, which is enough to convince me
> that it's doing TCO. Under CLISP (which doesn't compile
> to native code) it's somewhat slower, but again it
> gets far enough that I'm sure it's doing TCO. (Also,
> the CLISP process isn't growing in size.) Those are
> the only Common Lisps I happen to have installed
> at present.

On my system, clisp 2.38 crashes when I run the following:

(defun test () (test))
(test)

This would seem to me to be about as simple a tail call as there can be. 
It should just be an infinite loop. However, it causes clisp to crash. I 
haven't analyzed the crash, but assume it is a stack allocation failure 
that is not gracefully caught.

Gregg
From: GB
Subject: Re: i cant make a loop that exits when a conditon is met
Date: 
Message-ID: <uCZEf.85169$0G.38669@dukeread10>
GB wrote:
> 
> On my system, clisp 2.38 crashes when I run the following:
> 
> (defun test () (test))
> (test)
> 
> This would seem to me to be about as simple a tail call as there can be. 
> It should just be an infinite loop. However, it causes clisp to crash. I 
> haven't analyzed the crash, but assume it is a stack allocation failure 
> that is not gracefully caught.

However, disassembly implies otherwise, so I don't really know what is 
happening.

CL-USER> (disassemble 'test)

Disassembly of function TEST
0 required arguments
0 optional arguments
No rest parameter
No keyword parameters
3 byte-code instructions:
0     (JMPTAIL 0 1 L4)
4     L4
4     (JMPTAIL 0 1 L4)
NIL

Gregg
From: Pascal Bourguignon
Subject: Re: i cant make a loop that exits when a conditon is met
Date: 
Message-ID: <87vevv5ono.fsf@thalassa.informatimago.com>
GB <··@invalid.invalid> writes:

> GB wrote:
>> On my system, clisp 2.38 crashes when I run the following:
>> (defun test () (test))
>> (test)
>> This would seem to me to be about as simple a tail call as there can
>> be. It should just be an infinite loop. However, it causes clisp to
>> crash. I haven't analyzed the crash, but assume it is a stack
>> allocation failure that is not gracefully caught.
>
> However, disassembly implies otherwise, so I don't really know what is
> happening.

What is happening is that clisp contains an interperter and a compiler
and that of course, TCO is only done by the compiler.

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

"Logiciels libres : nourris au code source sans farine animale."
From: GB
Subject: Re: i cant make a loop that exits when a conditon is met
Date: 
Message-ID: <PB9Ff.85224$0G.3038@dukeread10>
Pascal Bourguignon wrote:
> GB <··@invalid.invalid> writes:
> 
>> GB wrote:
>>> On my system, clisp 2.38 crashes when I run the following:
>>> (defun test () (test))
>>> (test)
>>> This would seem to me to be about as simple a tail call as there can
>>> be. It should just be an infinite loop. However, it causes clisp to
>>> crash. I haven't analyzed the crash, but assume it is a stack
>>> allocation failure that is not gracefully caught.
>> However, disassembly implies otherwise, so I don't really know what is
>> happening.
> 
> What is happening is that clisp contains an interperter and a compiler
> and that of course, TCO is only done by the compiler.
> 

I don't see that TCO "of course" is only done by the compiler. The 
interpreter could generate TCO code when it interprets the defun. Scheme 
interpreters do this (as they are required to do).

But it seems that you are correct that the clisp interpreter does not do 
the optimization, because the compiled version of test does not crash.

I now see that the disassemble function automatically compiles its 
argument if necessary before disassembling it, so that explains why 
(disassemble 'test) show a (JMPTAIL 0 1 L4) instead of a call even prior 
to compilation.

Gregg
From: Pascal Bourguignon
Subject: Re: i cant make a loop that exits when a conditon is met
Date: 
Message-ID: <87d5i397f1.fsf@thalassa.informatimago.com>
Gareth McCaughan <················@pobox.com> writes:
>   | (defun wibble (n)
>   |   (when (zerop (mod n 1000000)) (format t "~&~A~%" (/ n 1000000)))
>   |   (wibble (1+ n)))
>   | 
>   | (compile 'wibble)
>   | 
>   | (wibble 0)
>
> runs happily and quickly up to at least n=140 on my
> machine under CMU CL, which is enough to convince me
> that it's doing TCO. Under CLISP (which doesn't compile
> to native code) it's somewhat slower, but again it
> gets far enough that I'm sure it's doing TCO. (Also,
> the CLISP process isn't growing in size.) Those are
> the only Common Lisps I happen to have installed
> at present.
>
> (By "doing TCO" I mean "converting tail recursion
> into a non-allocating branch, for this function
> on this occasion", not e.g. "turning all tail calls,
> without exception, into branches".)

You can use DISASSEMBLE to see it:

> (disassemble (compile (defun wibble (n)
   (when (zerop (mod n 1000000)) (format t "~&~A~%" (/ n 1000000)))
   (wibble (1+ n)))))

Disassembly of function WIBBLE
(CONST 0) = 1000000
(CONST 1) = #<COMPILED-FUNCTION WIBBLE-1>
(CONST 2) = *STANDARD-OUTPUT*
(CONST 3) = 1/1000000
1 required argument
0 optional arguments
No rest parameter
No keyword parameters
reads special variable: *STANDARD-OUTPUT*
14 byte-code instructions:
0     L0
0     (LOAD&PUSH 1)
1     (CONST&PUSH 0)                      ; 1000000
2     (CALLS2&PUSH 184)                   ; MOD
4     (CALLS2&JMPIFNOT 146 L18)           ; ZEROP
7     (CONST&PUSH 1)                      ; #<COMPILED-FUNCTION WIBBLE-1>
8     (GETVALUE&PUSH 2)                   ; *STANDARD-OUTPUT*
10    (CONST&PUSH 3)                      ; 1/1000000
11    (LOAD&PUSH 4)
12    (CALLSR&PUSH 2 55)                  ; *
15    (CALLSR 2 21)                       ; FUNCALL
18    L18
18    (LOAD&INC&PUSH 1)
20    (JMPTAIL 1 3 L0)
NIL

Yep, there's a JMPTAIL instead of a CALL :-)



-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
In deep sleep hear sound,
Cat vomit hairball somewhere.
Will find in morning.
From: Gareth McCaughan
Subject: Re: i cant make a loop that exits when a conditon is met
Date: 
Message-ID: <877j8a7t3y.fsf@g.mccaughan.ntlworld.com>
Pascal Bourguignon wrote:

[I wrote that some code ...]
>> runs happily and quickly up to at least n=140 on my
>> machine under CMU CL, which is enough to convince me
>> that it's doing TCO. Under CLISP (which doesn't compile
>> to native code) it's somewhat slower, but again it
>> gets far enough that I'm sure it's doing TCO. (Also,
>> the CLISP process isn't growing in size.) Those are
>> the only Common Lisps I happen to have installed
>> at present.
...
> You can use DISASSEMBLE to see it:

D'oh!

-- 
Gareth McCaughan
.sig under construc
From: Joe Marshall
Subject: Re: i cant make a loop that exits when a conditon is met
Date: 
Message-ID: <1139098511.523346.7910@f14g2000cwb.googlegroups.com>
Gareth McCaughan wrote:
>
>   - I don't think any CL implementation optimizes them
>     as fully as the Scheme standard requires all conforming
>     Scheme implementations to do.

Both Allegro Common Lisp and Lispworks will optimize tail calls as
fully as any Scheme implementation when the appropriate flags are set.

(There is a slight bit of trickiness with regard to special variables.
Scheme implementations that support `fluid-let' or `parameterizations'
are not tail-recursive at those constructs, so I think it is fair to
let Common Lisp not be tail-recursive there as well.)
From: Marcin 'Qrczak' Kowalczyk
Subject: Re: i cant make a loop that exits when a conditon is met
Date: 
Message-ID: <87bqxnb7xy.fsf@qrnik.zagroda>
·········@aol.com writes:

> does CL have tail-call-optamazation

I guess most CL implementations optimize tail recursion but not
tail calls.

I might be wrong however, this is just a guess.

-- 
   __("<         Marcin Kowalczyk
   \__/       ······@knm.org.pl
    ^^     http://qrnik.knm.org.pl/~qrczak/
From: Thomas Schilling
Subject: Re: i cant make a loop that exits when a conditon is met
Date: 
Message-ID: <44kh04F2ksj2U1@news.dfncis.de>
Marcin 'Qrczak' Kowalczyk wrote:

> I guess most CL implementations optimize tail recursion but not
> tail calls.
> 
> I might be wrong however, this is just a guess.
> 

Tail calls can easily be optimized if the called function has fewer or
the same number of arguments, or no stack arguments (usually <= 3).
Otherwise you'd have to do complicated stack-frame transformations or
calling conventions. Tail-recursive calls are the simple because the
called function has the same number of arguments (trivially).

I'd guess most CL implementations do TCO under the above circumstances.