123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234 |
- ---
- output: github_document
- ---
- <!-- README.md is generated from README.Rmd. Please edit that file -->
- ```{r, include = FALSE}
- 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
- <!-- badges: start -->
- <!-- badges: end -->
- 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
- ``` r
- remotes::install_github("dirkschumacher/llr")
- ```
- ## Intro
- ```{clojure}
- (->
- 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
- ```{r}
- library(llr)
- interp <- llr_env$new()
- interp$eval("(+ 1 1)")
- ```
- Also see some [Advent Of Code solutions](https://github.com/dirkschumacher/aoc2020) in llr.
- ### REPL
- It also has a (limited) REPL
- ```{r, eval=FALSE}
- interp <- llr_env$new()
- interp$repl()
- ```
- ## Special forms
- ### Data Types
- #### Lists
- ```{clojure}
- ; this is a list
- '(1 2 3 4 5 6)
- ; an unquoted list is a function call
- (+ 1 2 3 4 5 6)
- ```
- #### Vectors
- ```{clojure}
- [1 2 3 4]
- ```
- #### Maps
- ```{clojure}
- {: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.
- ```{clojure}
- (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.
- ```{clojure}
- (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`.
- ```{clojure}
- (def is-even
- (fn [number]
- (loop [cnt number]
- (if (zero? cnt)
- true
- (if (< cnt 0) false (recur (- cnt 2)))))))
- ```
- ```{clojure}
- (is-even 5001)
- ```
- ```{clojure}
- (is-even 5000)
- ```
- ### Namespaces
- Every top level definition is part of a namespace
- ```{clojure}
- (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
- ```{clojure}
- #_ (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.
- ```{clojure}
- (r/set.seed 1)
- (def rand-numbers (r/stats::rnorm :n 10))
- (r/mean rand-numbers)
- ```
- ## Design Goals
- * Have fun, experiment and learn :)
- * Build a clojure-like language that supports R-interop using the `r/` namespace.
- * Thus the core language should feel like clojure and support some of clojures's core
- functions, but still make it easy to work with R's internal data structures.
- ## Contributing
- * Please read the code-of-conduct and also be aware that this a fun project,
- so things will break and progress is valued prefect code (at the moment).
- * However everyone is invited to play around with the language, learn together,
- extend it, document things, fix bugs and propose features.
- ## Code of Conduct
- Please note that the llr project is released with a [Contributor Code of Conduct](https://contributor-covenant.org/version/2/0/CODE_OF_CONDUCT.html). By contributing to this project, you agree to abide by its terms.
|