README.Rmd 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. ---
  2. output: github_document
  3. ---
  4. <!-- README.md is generated from README.Rmd. Please edit that file -->
  5. ```{r, include = FALSE}
  6. knitr::opts_chunk$set(
  7. collapse = TRUE,
  8. comment = "#>",
  9. fig.path = "man/figures/README-",
  10. out.width = "100%"
  11. )
  12. knitr::knit_engines$set(
  13. clojure = llr::knitr_language_engine()
  14. )
  15. ```
  16. # llr
  17. <!-- badges: start -->
  18. <!-- badges: end -->
  19. 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.
  20. 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!
  21. ## Installation
  22. ``` r
  23. remotes::install_github("dirkschumacher/llr")
  24. ```
  25. ## Intro
  26. ```{clojure}
  27. (->
  28. r/datasets::mtcars
  29. (r/dplyr::filter (r/base::`>` hp 100))
  30. (r/dplyr::summarise :count (r/dplyr::n) :mean_mpg (r/mean mpg))
  31. (r/tibble::as_tibble))
  32. ```
  33. Or run it from R
  34. ```{r}
  35. library(llr)
  36. interp <- llr_env$new()
  37. interp$eval("(+ 1 1)")
  38. ```
  39. Also see some [Advent Of Code solutions](https://github.com/dirkschumacher/aoc2020) in llr.
  40. ### REPL
  41. It also has a (limited) REPL
  42. ```{r, eval=FALSE}
  43. interp <- llr_env$new()
  44. interp$repl()
  45. ```
  46. ## Special forms
  47. ### Data Types
  48. #### Lists
  49. ```{clojure}
  50. ; this is a list
  51. '(1 2 3 4 5 6)
  52. ; an unquoted list is a function call
  53. (+ 1 2 3 4 5 6)
  54. ```
  55. #### Vectors
  56. ```{clojure}
  57. [1 2 3 4]
  58. ```
  59. #### Maps
  60. ```{clojure}
  61. {:a 1 :b 2}
  62. ```
  63. ### Symbols
  64. ```{clojure, eval = FALSE}
  65. x
  66. ```
  67. ```{clojure, eval = FALSE}
  68. namespaced.variable/x
  69. ```
  70. ```{clojure, eval = FALSE}
  71. :keyword
  72. ```
  73. ```{clojure, eval = FALSE}
  74. "character"
  75. ```
  76. ```{clojure, eval = FALSE}
  77. 10 ; integer
  78. ```
  79. ```{clojure, eval = FALSE}
  80. 10.42 ; double
  81. ```
  82. ### Functions
  83. ```{clojure, eval = FALSE}
  84. (fn [a b] (+ a b))
  85. (fn this
  86. ([] 0)
  87. ([a] a)
  88. ([a b] (+ a b))
  89. ([a b & more] (reduce + (concat [a b] more))))
  90. ```
  91. ### def
  92. `def` defines a symbol in a namespace and assignes it a name.
  93. ```{clojure}
  94. (def x 1)
  95. (def plus (fn [a b] (+ a b)))
  96. (plus x x)
  97. ```
  98. ### Meta-data
  99. Symbols and values can hold meta-data. That meta-data needs to be a map at the moment.
  100. ```{clojure}
  101. (def ^{:const true} x ^{:meta "hello"} [ 1 2 3])
  102. (meta x)
  103. ```
  104. Meta-data on symbols is currently only available to the reader.
  105. ### Macros
  106. Macros are also supported. Macros are functions bound to a name with meta data `{:macro true}`.
  107. In a macro you can use syntax-quote `<backtick>` together with the unquote `~` and unquote-splice `~@` operators.
  108. ```{clojure}
  109. (defmacro infix [operand1 operator operand2]
  110. `(~operator ~operand1 ~operand2))
  111. (infix 1 + 1)
  112. ```
  113. ### Recursion
  114. Similar to Clojure llr uses `recur` to jump to a recursion point currently only defined by `loop`.
  115. ```{clojure}
  116. (def is-even
  117. (fn [number]
  118. (loop [cnt number]
  119. (if (zero? cnt)
  120. true
  121. (if (< cnt 0) false (recur (- cnt 2)))))))
  122. ```
  123. ```{clojure}
  124. (is-even 5001)
  125. ```
  126. ```{clojure}
  127. (is-even 5000)
  128. ```
  129. ### Namespaces
  130. Every top level definition is part of a namespace
  131. ```{clojure}
  132. (ns product.lib)
  133. (defn compute [a b] (+ a b))
  134. (ns user)
  135. (product.lib/compute 10 32)
  136. ```
  137. ### Reader Dispatch
  138. The reader switches to a different set of interpretations of the next symbol when reading the character `#`.
  139. ### `#_` ignores the next form
  140. ```{clojure}
  141. #_ (r/stop "error")
  142. "Yay"
  143. ```
  144. ### R interop
  145. 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.
  146. ```{clojure}
  147. (r/set.seed 1)
  148. (def rand-numbers (r/stats::rnorm :n 10))
  149. (r/mean rand-numbers)
  150. ```
  151. ## Design Goals
  152. * Have fun, experiment and learn :)
  153. * Build a clojure-like language that supports R-interop using the `r/` namespace.
  154. * Thus the core language should feel like clojure and support some of clojures's core
  155. functions, but still make it easy to work with R's internal data structures.
  156. ## Contributing
  157. * Please read the code-of-conduct and also be aware that this a fun project,
  158. so things will break and progress is valued prefect code (at the moment).
  159. * However everyone is invited to play around with the language, learn together,
  160. extend it, document things, fix bugs and propose features.
  161. ## Code of Conduct
  162. 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.