Arithmetic and Stacks

More Arithmetic

In the last section, we learned some basic arithmetic using + and *. However, froth incorporates a host of arithmetic expressions. Eagle-eyed readers may have spotted that we’ve only been working with commutative operations, meaning the order doesn’t matter (a+b = b+a). What happens when we use non-commutative expressions, such as division or exponentiation?

When froth executes words, it always treats the top of the stack as the last argument to the expression. This means that, for something like a b /, b is on the top of the stack and the result is a / b. froth uses R for its mathematical operations, so you don’t have to worry about things like converting between integers and doubles, or double vs. single length numbers.

The following mathematical operations are all built into froth:

Stack Operators

Unfortunately, there are some problems that just can’t be solved with stacks and postfix…at least, not without more tools. Consider the equation (a-b)/c. In postfix, this would be a b - c /. Now, if we wanted to write a word with definition ( c a b -- d ) that applies the function (a-b)/c, you’d find that it isn’t quite possible with the tools we have. Defining : SOLUTION? - / would instead apply c / (a - b), which isn’t quite right. What we need is a way to swap the top two values, so that we run (a-b)/c.

This is where stack operators come in handy. The operator we’re looking for is the aptly named SWAP ( a b -- b a ). which swaps the first two elements of the stack. Using this, we can write our definition:

fr> : TRYTHIS ( c a b -- d ) - swap / ;
ok.
fr> 4 2 1 trythis .
0.25 ok.

(2-1)/4 = 1/4 = 0.25, so this works! Here are a couple other stack operators that are often useful:

We also have a set of stack operators that work on pairs of numbers, but perform the same functions:

Two stacks?

froth actually has two stacks. The main one, the parameter stack, is what you’ll spend the majority of your time working with. Whenever we “push to the stack”, that’s referring to the parameter stack.

However, froth also has a second stack called the Return Stack. It’s possible for you to use this stack as a sort of “temporary space” to hold values while you process other things. It’s very important to ensure you clear the values on this temporary stack before you finish processing! froth is much more forgiving than Forth on this point, but it’s good to get in the practice of good Forth code.

This can sometimes be very useful. For instance, say we wanted to swap the second and third elements of the stack (that is, go from 2 3 1 to 3 2 1). We can do this with:

fr> 2 3 1
ok.
fr> >R SWAP R>
ok.
fr> .s
[[1]]
[1] 1

[[2]]
[1] 2

[[3]]
[1] 3

[[4]]
NULL

ok.

Fundamental Forth gives an excellent example of using these operators: suppose we want to write a function quadratic ( a b c x -- n ) that returns ax^2 + bx + c.

fr> : QUADRATIC ( a b c x -- n ) >r swap rot r@ * + r> * + ; 
ok.
fr> 2 7 9 3 quadratic .
48 ok.

Other Miscellaneous operators

For completeness, here are some other arithmetic operations:

We also have some funky double operators:

If you’re coming from Forth, you may recognize these are operations using double-length values as intermediates for increased precision. However, since froth uses R internals for operations, there’s no difference between single and double length values.

Words in this chapter