|
|
CS 3721
Programming Languages
Spring 2014 |
1. Lisp Functions
|
Initial Problems:
These involve just setq.
and separately calculate each of the three items below:
hypotsq = a^2 + b^2
hypot = sqrt(a^2 + b^2)
vol = (4/3)*pi*a^3 (answer: vol is 113.097336)
(You must convert these to Lisp notation, using nested S-expressions,
with the function first. Square root is "sqrt".
Lisp has no built-in sqr function, though we can easily write one.)
Problem 1.2: More numeric computations. Do
> (setq a 1L0)
> (setq b -1L0)
> (setq c -1L0)
and separately use setq to assign each of the two items below:
r1 = (-b + sqrt(b^2 - 4*a*c))/(2*a)
r2 = (-b - sqrt(b^2 - 4*a*c))/(2*a)
(Putting an "L0" at the of the constants will force the
arithmetic to be done as long doubles.)
Lisp Conditionals:
Lisp has a traditional if-then-else but we are going to teach
(and use) only the original general cond:
- cond is another special function that evaluates
its arguments in a sequential way:
Conditional: in place of if-then-else |
(cond
(pred1 result1)
(pred2 result2)
...
(t default))
|
Here each predi is a predicate. A predicate is
a function that returns either true (t) or
false (nil or ()). If pred1
is true, the value of the cond is result1,
and no more of the cond is evaluated. Otherwise if
pred2
is true, the value of the cond is result2,
and no more of the cond is evaluated, and so forth.
If none of the predicates is true, then the value will be default.
Lisp Functions:
- defun is special function that does not evaluate
its arguments, but produces the side effect of defining a function.
Below shows the form of a definition and of a call.
defun: define a function |
(defun fname (v1 v2 ... vn) ; definition of function
;; body of function (sequence of S-expressions)
;; value of last one is value returned
)
(fname arg1 arg2 ... argn) ; call of function
|
Notice that the form of the call is slightly different from
the look of the function definition. In the call, there
is a single list with the function name at its head (car).
In the function definition the function name is separate,
before the list of parameters.
- In the above fname is the name of the function,
v1 v2 ... vn are the n
formal parameters which must be identifiers,
arg1 arg2 ... argn are the n
actual parameters which can be any S-expressions,
which will all be evaluated before the function is applied
using the supplied definition.
Examples:
The first function we gave was the factorial:
(defun factorial (n) ; a function definition
(cond ((= n 0) 1)
(t (* n (factorial (- n 1)))) ))
|
Or, using 1- to subtract 1 from a single argument:
(defun factorial (n) ; a function definition
(cond ((= n 0) 1)
(t (* n (factorial (1- n)))) ))
|
Here is the combinations function c rewritten slightly:
(defun c (r k) ;;; comp of r things, k at a time
(cond ((= k 0) 1)
((= k r) 1)
(t (+ (c (- r 1) k) (c (- r 1) (- k 1)))) ))
|
Further Problems:
This page concludes with a sequence of examples and problems
for Recitation 1.
- First use the operator / with integers,
so that the answers are rational numbers.
[Try out
n = 10, 20.
As a check, the value of (harmonic 10)
should be 7381 / 2520.]
- Then rewrite the harmonic function using constants with
a decimal point and with "L0" at the end to force Lisp to
use long double numbers. [Now as a check the value of
(harmonic 10) should start out
2.928968253968.]
Problem 1.4: Write a recursive function fibonacci that will
return the nth fibonacci number F[n], where
F[0] = 0, F[1] = 1, and F[n] = F[n-1] + F[n-2].
[For reference, (fibonacci 10)
should return 55,
(fibonacci 20) returns 6765
after a few seconds,
(fibonacci 30) returns 832040 after a few
seconds, and (fibonacci 35) may take a minute
to return 9227465.
Problems Involving "raise-to-a-power"
or "pow":
Consider a recursive function to raise a number to a positive
integer power:
pow function |
(defun pow (a b)
(cond ((= b 0) 1)
(t (* (pow a (1- b)) a)) ))
|
Notice that here a can be any number at all: integer, float,
fraction, zero, positive, negative.
In the above program, b is assumed to be a non-negative
integer. (The program returns 1 for (pow 0 0),
while this should be undefined.)
Question: Without using clisp, try to decide what
the result would be if b is negative,
say the result of (pow 2 -3).
Now actually try this in Lisp.
We would like to print debug information at each recursive
invocation of the function. The code below illustrates some of
Lisp's weird output functions:
Output
Functions in Lisp |
(princ '|pow: |) ;; prints the chars inside | |
(prin1 a) ;; prints the value of a
(terpri) ;; prints a newline
|
pow function |
(defun pow (a b)
(princ '|pow: |)(prin1 a)(princ '| |)(prin1 b)(terpri)
(cond ((= b 0) 1)
(t (* (pow a (1- b)) a)) ))
| > (pow 11 6)
pow: 11 6
pow: 11 5
pow: 11 4
pow: 11 3
pow: 11 2
pow: 11 1
pow: 11 0
1771561 | > (pow 2972 4)
pow: 2972 4
pow: 2972 3
pow: 2972 2
pow: 2972 1
pow: 2972 0
78018073190656 | > (pow 0.3L0 6)
pow: 0.3L0 6
pow: 0.3L0 5
pow: 0.3L0 4
pow: 0.3L0 3
pow: 0.3L0 2
pow: 0.3L0 1
pow: 0.3L0 0
7.2900000000000000015L-4
Close to: 0.000729
| > (pow 5/7 5)
pow: 5/7 5
pow: 5/7 4
pow: 5/7 3
pow: 5/7 2
pow: 5/7 1
pow: 5/7 0
3125/16807
|
Problem 1.7: Rewrite your pow function as a function
rtp ("raise to power", just to have another name) that
is based on the recursive definition below.
Here we are back to assuming that b is a non-negative integer.
[For convenience I wrote and used another
lisp function sqr that returns
the square of its argument.]
[Um, don't panic. Follow the definition carefully using
a cond, with the third case (b = 0) first.
To check if b is odd, you can use
(= (rem b 2) 1).]
After debugging this function (or before if you like), add the
debug code to show each recursive function call (the code shown above
in red for the second version of the pow function).
For testing, try - (rtp 7 23)
[As a check, the answer should be:
(rtp 7 23) |
> (rtp 7 23)
rtp: 7 23
rtp: 7 11
rtp: 7 5
rtp: 7 2
rtp: 7 1
rtp: 7 0
27368747340080916343
|
- (rtp 2 2143).
- How many recursive calls were there in part b above?
How many recursive calls would there be with the call
(pow 2 2143)
where pow is defined as at the beginning of this section?
Guess (or figure out) the
asymptotic performance of the the rtp algorithm as a function
of the second parameter (b)? (Hey, why did you take the
algorithms course if not to answer questions like this?)
( Revision date: 2014-04-01.
Please use ISO
8601, the International Standard.)
|