This post will probably come back to haunt me, but functional programming doesn't sit well with me. I'm trying again to read through SICP. Last time I tried, I lost track of it and gave up after a few chapters. This time I hope to persevere, and I'm trying to go more slowly through the examples to really understand things.
I was trying to do some of the exercises in chapter 1 today, and pretty much bombing on all of them. Most of the exercises I've seen so far in SICP sound like they came out of a math book. "There is a clever algorithm for computing the Fibonacci numbers in a logarithmic number of steps..." Uh huh. This is not the kind of problem I enjoy, or have even the slightest use for. But maybe the problems are only pointless examples to illustrate a point, like "mass-less friction-less pulleys" in physics textbooks. I can live with that I guess.
Here is a Scheme example from SICP to compute b to the power of n:
(define (expt b n) (expt-iter b n 1)) (define (expt-iter b counter product) (if (= counter 0) product (expt-iter b (- counter 1) (* b product))))
This is presented as a wonderful and novel functional programming approach.
One of my problems is the amount of brain-work it takes to understand this. OK, start with EXPT. We take
n, and then call some recursive helper function with b, n, and a state variable
product initialized to 1 HEY WAIT A SECOND THERE'S A STATE VARIABLE?!
This is one way to cheat in functional programming, I guess.
product is a variable name / symbol, which describes "something" that takes on different values over time, each value representing the same "thing" in different states. That qualifies as a state variable to me. The only difference is that the state variable is actually N different variables (with the same name) splattered across a bunch of frames on a call stack, instead of an abstraction of a single simple bucket where I dump a value.
Now in EXPT-ITER,
counter starts at n, and every time the function calls itself, counter decreases by 1, until you reach 0, at which point EXPT-ITER stops calling itself and returns something. So this is a perverted, inside-out way of saying "do something N times", where every iteration costs me a recursive function call. Nice.
OK, what are we doing N times? We're multiplying
product, which starts at 1, by
b, which then becomes the new value of
product next time around.
SO WHY NOT JUST WRITE THAT TO BEGIN WITH?
(defun simple-expt (b n) (let ((total 1)) (dotimes (i n) (setf total (* total b))) total))
In Common Lisp this reads as "Let total start at 1. N times, set total to the product of total and b. Then return total." This is EXACTLY what the Scheme version is doing. Except I don't have to turn my brain inside-out to write it down this way. The CL code reads exactly like what the program is doing.
When all you have is a hammer, every problem looks like a nail. When all you have is recursion, every problem looks like it should be solved using recursion, I guess.
Actually if I ignore the functional programming bits, SICP is a great book. There are a lot of good things in there. But (so far) Scheme isn't one of them.