Stuff we can re-use
Values
Push
dup
factorial
rpn-func macro
Main loop
conclusion
In my last phlog, I wrote a simple RPN calculator in scheme, but even
though it wasn't particularly "functional", the stack was a global
variable that we modified in place. Not good form a functional point of
view. So lets rewrite our calculator to be more functional. It can't
really be purely functional because scheme isn't purely functional
itself. But we can make our best effort to be as functional as possible.
Stuff we can re-use
===================
We can't keep alot of our old implementation, we just have to change
the functions that alter the stack to return the altered stack
instead, and also take the stack as an argument.
Like /pop!/ use to just alter the stack using /set!/, but insetad
/pop/ will take the stack as its argument and return the popped
variable and the stack.
I could have just one-linered this but its easier to see what is going
on if i use a /let/ and name the return values nicely.
Values
======
If you know how multiple return values work in scheme, then you can
skip this section. But otherwise here we go!
You can do multiple return values in scheme several ways, the easiest
is probably to build a list and return the list where each element is
one of the return values.
But when accessing each variable, it requires some list dancing to
access but is my personal usual way of handling multiple return
values, but i'm choosing to go with /values/ this time because I
haven't used it before.
And the third is continuation passing style, which is strange
looking. You return a function acting on your return variables that
was passed to your function.
,----
| (define (fact x)
| (define (fact-iter n current)
| (if (= n 1)
| current
| (fact-iter (- n 1) (* n current))))
| (fact-iter x 1))
`----
rpn-func macro
==============
We will have to change this macro so that it returns the stack and
also uses the new /pop/ and /push/. I will also change it just a
function because it's not really a good use for a macro.
So you can see I used /let*-values/ to capture the return values of
popping the stack twice, and because we used /let*-values/ instead of
/let-values/, we can use the previous varibles so that the modified
stack can be passed to the next /pop/.
The main loop doesn't need too much changing, but there are some
things we need to change.
1. Initial call to loop needs another variable, the stack.
2. change all the /rpn-func/ calls to use the stack.
3. change the implementation of modulo, factorial etc
4. change $ to use /let-values/ to display the top element of the
stack then return.
The only problem is how do we get what is returned form the /cond/ to
our loop invocation. One way is to have every expression in the cond
call /loop/, but that seems ugly to me. If I find a better solution
later I will phlog about it.