One of the perks of froth is being able to run on top of
R. This means we can take advantage of some nice R features–for example,
the .R word in froth will print the top
element of the stack using R’s print method.
There are also a number of functions designed to allow R users to
interact with the froth environment without having to go
into the commandline.
The first of these is froth.parse, which evaluates a
character vector within a froth environment.
froth.parse("1 2 3 . . .")## 3 2 1
This environment persists, so we can make multiple calls and have our stack still remember what’s in it.
froth.parse("1 2 3")
froth.parse(". . .")## 3 2 1
However, this is just printing out the values. What if we wanted to
actually pop a value from the froth stack to
R? This is accomplished with froth.RPop().
froth.parse("1")
x <- froth.RPop()
x## [[1]]
## [1] 1
You’ll notice that the result is in a list. This is because
froth just returns the entire top entry of the stack and
relies on the user to process it further.
It’s also possible to push arbitrary R objects to froth
using froth.RPush.
froth.RPush(\(x) x**2)
froth.parse('.s')## [[1]]
## \(x) x**2
##
## [[2]]
## NULL
Now we have an R function on top of the stack! This stack state
persists if we drop into a commandline, so you can push object from R,
use froth() to work with them in froth, then
return to R to pull them back (or do it all with
froth.parse).
R has a lot of nice functions, and not all of them are in
froth. However, it’s possible to ask froth to
make its own version of an R function. Let’s say we wanted to define a
function rnorm ( n mu sd -- x ) that calls
rnorm(n, mu, sd) using the top three entries of the stack.
We can use froth.RDefine for this. This function takes
three arguments: the name of the new word in froth, the R
function to associate with it, and the number of arguments to provide.
In this case, we’ll need 3 arguments. We can also pass a number to
froth.RPop() to ask it for more than a single value.
froth.parse('clear')
froth.RDefine('R_rnorm', rnorm, 3L)
froth.parse("5 0 0.5 R_rnorm")
r <- unlist(froth.RPop(5L))
r## [1] 0.3023257 -0.2057518 0.1636908 0.6247276 -0.6234755
It’s important to note that froth will pull the
arguments in the same way it pulls arguments for internal functions.
That is, the top of the stack becomes the last argument, the next
becomes the second to last, etc. This is equivalent to how arguments are
parsed for words like / or ^.
A quick detail of some other important functions:
saveFrothSession and
loadFrothSession allow you to save and load a
froth environment, respectively. This will save any
variables and words you’ve defined from within froth.
froth.RDefine words will not be saved.froth.source is identical to froth.parse,
except that it reads from a file rather than from a character
vector.writeFrothDictionary will write all your defined words
to the console or (if a file is specified) to a file. This is a good
utility for exporting your word definitions.