1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-20 11:40:18 +02:00

Apply patch from M. Luedde on use of tail recursion to avoid stack overflow

This commit is contained in:
Neil Jerram 2002-07-16 20:57:34 +00:00
parent 3063e30a6d
commit c5d1306193
2 changed files with 58 additions and 12 deletions

View file

@ -1,3 +1,13 @@
2002-07-16 Neil Jerram <neil@ossau.uklinux.net>
* guile-tut.texi (Jump Start): Apply patch from M. Luedde on use
of tail recursion to avoid stack overflow (with minor editing).
2002-07-14 Neil Jerram <neil@ossau.uklinux.net>
* guile-tut.texi (Jump Start):
(Jump Start):
2001-11-18 Neil Jerram <neil@ossau.uklinux.net> 2001-11-18 Neil Jerram <neil@ossau.uklinux.net>
* guile-tut.texi (History of Guile and its motivations): Update * guile-tut.texi (History of Guile and its motivations): Update

View file

@ -99,6 +99,7 @@ by the author.
* Type Index:: * Type Index::
@end menu @end menu
@node Jump Start @node Jump Start
@chapter Jump Start @chapter Jump Start
@ -106,8 +107,8 @@ by the author.
Before giving an overview of Guile, I present some simple commands and Before giving an overview of Guile, I present some simple commands and
programs that you can type to get going immediately. programs that you can type to get going immediately.
Start by invoking the Guile interpreter (usually you do this by just Start by invoking the Guile interpreter. Usually you do this by just
typing @code{guile}). Then type (or paste) the following expressions at typing @code{guile}. Then type (or paste) the following expressions at
the prompt; the interpreter's response is preceded (in this manual) by the prompt; the interpreter's response is preceded (in this manual) by
@result{}. @result{}.
@ -118,11 +119,26 @@ the prompt; the interpreter's response is preceded (in this manual) by
(+ 20 35) (+ 20 35)
@result{} 55 @result{} 55
(define (recursive-factorial n) (define (recursive-factorial n)
(if (= n 0) (if (zero? n)
1 1
(* n (recursive-factorial (- n 1))))) (* n (recursive-factorial (- n 1)))))
(recursive-factorial 5) (recursive-factorial 5)
@result{} 120 @result{} 120
(quit)
@end lisp
In this example we did some simple arithmetic @code{(+ 20 35)} and got
the answer @code{55}. Then we coded the classic (and rather wasteful)
factorial algorithm and computed the factorial of @code{55}. Finally we
quit with @code{(quit)}.
@cindex bignumbers
We can find out about some of Scheme's nice features by asking for the
factorial of some big number, say @code{500}. On some systems the
correct answer will be returned (I do not indicate calling and leaving
the guile session anymore).
@lisp
(recursive-factorial 500) (recursive-factorial 500)
@result{} 1220136825991110068701238785423046926253574342803192842192413588 @result{} 1220136825991110068701238785423046926253574342803192842192413588
3858453731538819976054964475022032818630136164771482035841633787 3858453731538819976054964475022032818630136164771482035841633787
@ -142,15 +158,35 @@ the prompt; the interpreter's response is preceded (in this manual) by
3896881639487469658817504506926365338175055478128640000000000000 3896881639487469658817504506926365338175055478128640000000000000
0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000
<control-D>
@end lisp @end lisp
In this example we did some simple arithmetic @code{(+ 20 35)} and got The result is an example of Scheme's @emph{bignumbers}. However, there
the answer @code{55}. Then we coded the classic (and rather wasteful) are operating environments that provide (by default) too little stack
factorial algorithm, and got a glimpse of Scheme's nice space. They will instead produce an error message like this:
@emph{bignumbers} by asking for the factorial of 500. Then we quit
with @code{(quit)}. @lisp
@cindex bignumbers (recursive-factorial 500)
@print{}
ERROR: Stack overflow
ABORT: (stack-overflow)
@end lisp
Rather than enlarging the system's stack, we can implement the algorithm
such that it does not consume increasing stack space. This is called a
@emph{tail recursive} implementation. The following definition is tail
recursive and so should work on all systems.
@lisp
(define (tail-recursive-factorial n)
(define (loop k l)
(if (zero? k) l
(loop (- k 1) (* k l))))
(loop n 1))
(tail-recursive-factorial 500)
@result{} 1220136825991110068701238785423046926253574342803192842192413588
;; ... skipped
@end lisp
This is the most basic use of Guile: a simple Scheme interpreter. In This is the most basic use of Guile: a simple Scheme interpreter. In
the rest of this tutorial I will show you how Guile has many facets: it the rest of this tutorial I will show you how Guile has many facets: it