knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  fig.path = "man/figures/README-",
  out.width = "100%"
)
knitr::knit_engines$set(
  clojure = llr::knitr_language_engine()
)

llr

llr is a small, work in progress and just for fun clojure-like lisp on top of R's abstract syntax trees. Expressions are not interpreted, but are translated to R's AST and then interpreted by the R interpreter.

Most implementation details are sub-optimal, but the focus is on having fun and producing results instead writing perfect code. There are also many bugs and inconsistencies!

Installation

remotes::install_github("dirkschumacher/llr")

Intro

(->
  r/datasets::mtcars
  (r/dplyr::filter (r/base::`>` hp 100))
  (r/dplyr::summarise :count (r/dplyr::n) :mean_mpg (r/mean mpg))
  (r/tibble::as_tibble))

Or run it from R

library(llr)
interp <- llr_env$new()
interp$eval("(+ 1 1)")

Also see some Advent Of Code solutions in llr.

REPL

It also has a (limited) REPL

interp <- llr_env$new()
interp$repl()

Special forms

Data Types

Lists

; this is a list
'(1 2 3 4 5 6)
; an unquoted list is a function call
(+ 1 2 3 4 5 6)

Vectors

[1 2 3 4]

Maps

{:a 1 :b 2}

Symbols

```{clojure, eval = FALSE} x

```{clojure, eval = FALSE}
namespaced.variable/x

```{clojure, eval = FALSE} :keyword

```{clojure, eval = FALSE}
"character"

```{clojure, eval = FALSE} 10 ; integer

```{clojure, eval = FALSE}
10.42 ; double

Functions

```{clojure, eval = FALSE} (fn [a b] (+ a b))

(fn this ([] 0) ([a] a) ([a b] (+ a b)) ([a b & more] (reduce + (concat [a b] more))))

### def

`def` defines a symbol in a namespace and assignes it a name.

```{clojure}
(def x 1)
(def plus (fn [a b] (+ a b)))
(plus x x)

Meta-data

Symbols and values can hold meta-data. That meta-data needs to be a map at the moment.

(def ^{:const true} x ^{:meta "hello"} [ 1 2 3])
(meta x)

Meta-data on symbols is currently only available to the reader.

Macros

Macros are also supported. Macros are functions bound to a name with meta data {:macro true}.

In a macro you can use syntax-quote <backtick> together with the unquote ~ and unquote-splice ~@ operators.

(defmacro infix [operand1 operator operand2]
  `(~operator ~operand1 ~operand2))
(infix 1 + 1)

Recursion

Similar to Clojure llr uses recur to jump to a recursion point currently only defined by loop.

(def is-even 
  (fn [number] 
    (loop [cnt number]
      (if (zero? cnt)
        true
        (if (< cnt 0) false (recur (- cnt 2)))))))
(is-even 5001)
(is-even 5000)

Namespaces

Every top level definition is part of a namespace

(ns product.lib)
(defn compute [a b] (+ a b))
(ns user)
(product.lib/compute 10 32)

Reader Dispatch

The reader switches to a different set of interpretations of the next symbol when reading the character #.

#_ ignores the next form

#_ (r/stop "error")
"Yay"

R interop

All symbols starting with the namespace r/ are treated slightly differently. You can use that to refer to external R functions and symbols. In addition keywords are interpreted as named arguments.

(r/set.seed 1)
(def rand-numbers (r/stats::rnorm :n 10))
(r/mean rand-numbers)

Design Goals

Contributing

Code of Conduct

Please note that the llr project is released with a Contributor Code of Conduct. By contributing to this project, you agree to abide by its terms.



dirkschumacher/llr documentation built on Dec. 27, 2021, 10:13 p.m.