Interfacing with R

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 ^.

Saving and Loading

A quick detail of some other important functions: