Monday, November 17, 2008

A Factorial Example

To reinforce what we have learned so far, below is a longer example that uses a
while loop to compute the factorial function:

Example 1–13 A while loop to compute factorial.
proc Factorial {x} {
set i 1; set product 1
while {$i <= $x} {
set product [expr $product * $i]
incr i
return $product
Factorial 10
=> 3628800
The semicolon is used on the first line to remind you that it is a command
terminator just like the newline character. The while loop is used to multiply all
the numbers from one up to the value of x. The first argument to while is a boolean
expression, and its second argument is a command body to execute. The
while command and other control structures are described in Chapter 6.
The same math expression evaluator used by the expr command is used by
while to evaluate the boolean expression. There is no need to explicitly use the
expr command in the first argument to while, even if you have a much more
complex expression.
The loop body and the procedure body are grouped with curly braces in the
same way. The opening curly brace must be on the same line as proc and while.
If you like to put opening curly braces on the line after a while or if statement,
you must escape the newline with a backslash:
while {$i < $x} \
set product ...
Always group expressions and command bodies with curly braces.
More about Variables 13
I. Tcl Basics
Curly braces around the boolean expression are crucial because they delay
variable substitution until the while command implementation tests the expression.
The following example is an infinite loop:
set i 1; while $i<=10 {incr i}
The loop will run indefinitely.* The reason is that the Tcl interpreter will
substitute for $i before while is called, so while gets a constant expression 1<=10
that will always be true. You can avoid these kinds of errors by adopting a consistent
coding style that groups expressions with curly braces:
set i 1; while {$i<=10} {incr i}
The incr command is used to increment the value of the loop variable i.
This is a handy command that saves us from the longer command:
set i [expr $i + 1]
The incr command can take an additional argument, a positive or negative
integer by which to change the value of the variable. Using this form, it is possible
to eliminate the loop variable i and just modify the parameter x. The loop
body can be written like this:
while {$x > 1} {
set product [expr $product * $x]
incr x -1
Example 1–14 shows factorial again, this time using a recursive definition.
A recursive function is one that calls itself to complete its work. Each recursive
call decrements x by one, and when x is one, then the recursion stops.
Example 1–14 A recursive definition of factorial.
proc Factorial {x} {
if {$x <= 1} {
return 1
} else {
return [expr $x * [Factorial [expr $x - 1]]]

No comments: