```r

library(schemeR, warn.conflicts=FALSE) library(knitr)

options(width=80) knitr::opts_chunk$set( collapse = TRUE, comment = "#>", fig.path = "README-", warning = FALSE, message = FALSE, echo = TRUE, tidy = FALSE, size="small", linewidth=80 )

From https://github.com/yihui/knitr-examples/blob/master/077-wrap-output.Rmd

hook_output = knit_hooks$get('output') knit_hooks$set(output = function(x, options) { # this hook is used only when the linewidth option is not NULL if (!is.null(n <- options$linewidth)) { x = knitr:::split_lines(x) # any lines wider than n should be wrapped if (any(nchar(x) > n)) x = strwrap(x, width = n) x = paste(x, collapse = '\n') } hook_output(x, options) })

[![Build Status](https://img.shields.io/travis/wwbrannon/schemeR.svg?style=flat)](https://travis-ci.org/wwbrannon/schemeR)
[![CRAN_Status_Badge](https://www.r-pkg.org/badges/version/schemeR)](https://cran.r-project.org/package=schemeR)
[![Downloads](https://cranlogs.r-pkg.org/badges/schemeR)](https://cran.r-project.org/package=schemeR) [![License](https://img.shields.io/:license-mit-blue.svg?style=flat)](https://wwbrannon.mit-license.org/)

# schemeR

The schemeR package provides a Lisp-like mini-language within R, with a prefix syntax and versions of many of the usual Lisp operators (let, cond, do, functional programming utilities, etc.). Code written with this package is still valid R, but the differences from what R code normally looks like highlight the language's roots in Scheme.

Real Lisp macros (the "non-hygienic", defmacro-based variety) are also supported. The implementation hews more closely to the way macros work in Common Lisp than other macro implementations for R, such as the one in the gtools package. Future work on schemeR will include an exploration of hygienic macros and whether they can be implemented as well.

## Basic usage
The main entry point is the `schemeR()` function, which takes code written in this package's prefix style, translates it to the usual R syntax, and executes it.

For example, here are prefix and infix versions of a simple loop (the `invisible` is to hide final return values):
``` {r, echo=TRUE}
x <- sort(sample(1:10, 5, replace=TRUE))

# In the usual infix R syntax:
invisible(
for(i in x)
    print(1:i)
)

#Equivalent, but prefix:
schemeR({
.(invisible,
  .(`for`, i, x,
    .(print, .(`:`, 1, i))))
})

The . that appears in the prefix code is a function, which is how we can manage to write R this way and still have it parse. The unusual-for-Lisp syntax on display in prefix code is a consequence: lists must start with a .( rather than just a parenthesis, and elements are separated by commas rather than whitespace (because as far as R's parser is concerned, they're function arguments).

Despite its usefulness, the . function is just syntactic sugar: it generates a call to its first argument with all of its subsequent arguments, and requires a preprocessing step to be turned back into usable code. schemeR() does that preprocessing, with a few additional pieces of syntactic sugar, and executes the code that results.

Syntactic sugar

schemeR() understands a few pieces of infix syntactic sugar:

Lisp operators and other functions

A variety of Lisp operators are also included, a few of which are just syntactically convenient aliases for things in base R (to avoid backtick-quoting, so that for example one can write progn instead of `{`). Some of the included operators are:

Macros

This package's implementation of macros is closer to Common Lisp's version than other R implementations are. Specifically,

A working example of using macros demonstrates most package features. The macro below implements Python's list comprehensions:

schemeR({
.(defmacro, list.of, .(exp, s1, var, s2, lst, s3, test),
    .(cond, .(.(missing, test), .(set, test, TRUE))),
    .(let, .(.(result, .(gensym, "G1")), .(lvar, .(gensym, "G2"))),
        .b(.(let, .(.(.c(lvar), .c(lst))),
                .(do, .(.(.c(result), nil, .(cond, .(.c(test), .(append, .c(result), .c(exp))),
                                                   .(TRUE, .c(result)))),
                        .(.c(var), car(.c(lvar)), car(.c(lvar)))),
                      .(.(is.nil, .c(lvar)), .c(result)),
                      .(sset, .c(lvar), .(cdr, .c(lvar))))))))
})

# List comprehensions!
list.of(x^2, `for`, x, `in`, 1:10)
list.of(x^2, `for`, x, `in`, 1:10, `if`, x >= 5)

# But they look a bit more natural in prefix form:
schemeR(
    .(list.of, x^2, `for`, x, `in`, 1:10)
)

schemeR(
    .(list.of, x^2, `for`, x, `in`, 1:10, `if`, .(`>=`, x, 5))
)

# You have to backtick-quote "for", "in" and "if" because they're R reserved
# words, but you're free to use syntactic names if you want, because the macro
# discards those arguments anyway:
schemeR(
    .(list.of, x^2, with, x, of, 1:10)
)

schemeR(
    .(list.of, x^2, with, x, of, 1:10, where, .(`>=`, x, 5))
)

Installation

Install the released version from CRAN:

install.packages("schemeR")

Install the dev version from github:

install.packages("devtools")
devtools::install_github("wwbrannon/schemeR")


wwbrannon/schemeR documentation built on May 4, 2019, 12:03 p.m.