Statistical Lisp in R

docs

Implemention of Lisp-style sytnax and language design for the R programming language. Code written in SluRp will be translated to R and then executed in that environment.

This project isn’t intended as a production ready application or alternative to R but rather a fun project to learn something about the implementation of lisp and the core R language.

Quick-start Guide

Start the REPL:

Or you can run a SluRp script:

In the REPL you can enter the lisp-style commands:

Unlike R, arithmetic functions are applied over all arguments:

Create variables using the defparam function. This function returns the value associated with the variable name. These variables can then be references in the same scope.

As its implemented in the R environment, the usual statistical functions are readily available. Here we are taking 10 samples from a normal distribution with the centre and scale of 10. The return of this function is a vector of 10 elements.

Function arguments can be supplied using the :keyword form. For example:

In this example, we are once again calling the rnorm function and taking 10 samples from a normal distribution. But instead of supplying the arguments by the position they occur in the function call (number of samples, mean, and then standard deviation of the distribution), we are using keywords. When this form is evaluated in R this gets translated to:

rnorm(10, mean = 10, sd = 1)

As opposed to R base, most functions return a value. Take for example the print() function in R that prints the passed argument to the stream output. In SluRp, the argument that is passed to the function is printed to the stream and also returned.

Data types

Lisp is a list processor, but we’re working with R, so we have access to more complex data-types. One of which is the vector or c() data-type for simple storage and vector arithmetic. We can create a vector with squared-brackets, e.g. [1 2 3] is translated to c(1, 2, 3). This translation is necessary for when we’re using functions that expect vector arguments:

Creating functions

Anonymous functions can be created using a lambda expression. Take for example applying a function to a map (from the purrr package).

Anonymous functions can also be bound to a name. This is perhaps just a longer way of creating a function.

The shorter way to create a normal function is to use the defun function. The arguments to defun are the parameters of the function (or an optional empty list) and the body of the function i.e. what happens when the function is called.

Things to do:

  • [X] Lisp tokenisation
  • [X] Basic function application
  • [X] Vector notation
  • [X] Nested function application
  • [X] Function definitions
  • [X] Lambdas
  • [X] Variable assignments
  • [ ] Sets and Lists
  • [X] Keyword arguments
  • [ ] Macros
  • [ ] Pre-installed macros such as threading

Functions to implement

  • [ ] Cons
  • [ ] Listp
  • [ ] Atomp
  • [ ] Better evaluation - special symbols evaluate to themselves
  • [ ] Better tokenisation – should take into account the end of the list to allow scripts to run
  • [ ] Quote/Eval