
Advanced R presents useful tools and techniques for attacking many types of R programming problems, helping you avoid mistakes and dead ends. With more than ten years of experience programming in R, the author illustrates the elegance, beauty, and flexibility at the heart of R. The book develops the necessary skills to produce quality code that can be used in a variety of circumstances. You will learn: The fundamentals of R, including standard data types and functions Functional programming as a useful framework for solving wide classes of problems The positives and negatives of metaprogramming How to write fast, memory-efficient code This book not only helps current R users become R programmers but also shows existing programmers what’s special about R. Intermediate R programmers can dive deeper into R and learn new strategies for solving diverse problems while programmers from other languages can learn the details of R and understand why R works the way it does.
There is also Metaprogramming in R by Thomas Mailund, which seems good from the preview material I was able to find: https://www.apress.com/gp/book/9781484228807
For really powerful demonstrations of what R metaprogramming can do, see the Dplyr and Data.table packages.
Personally, I've used it to implement things like shorthand lambdas, the Clojure threading macro, and a function composition operator that constructs and evaluates an expression of nested calls to keep runtime overhead down to a minimum.
R macros are sometimes more powerful than true Lisp macros, in that there is no separation between the macro expansion phase and code execution. This is possible because R function arguments are lazily evaluated. The argument is a special "code object" that represents an expression. If you want to capture or change that expression, you can do so freely inside the function. So there is no need for macros, just functions that can capture unevaluated expressions.
Incidentally this also makes R very hard to optimize, since any function can do this at any time.
It is also available for free.
The tidyverse suite of Hadley Wickham is a great example of this, notably with the pipe operator %>% (similar to |> in F#) which is not part of the base language and yet could be very easily implemented. Julia's macros probably enables the same type of implementation, but I don't see how one would achieve it as easily in Python for example. Non-standard evaluation is another example of R's lispiness in action [0].
Also, consider how easy it is to walk R's S-exp. Expressions in R can only be one of four things: an atomic value, a name, a call or a pairlist. Wickham's Advanced R has a great intro on this [1].
I believe Wickham's amazing work with tidyverse (which really changes the way you code in R) is just the beginning of a rediscovery of R's inner lisp power, a kind of "R: the good parts" moment.
re: the Assignment operator http://www.studytrails.com/R/Core/AssignmentOperator.jsp
> However, there is a difference between the two operators. = is only allowed at the top level i.e. if the complete expression is written at the prompt. so = is not allowed in control structures. Here's an example:
> if (aa=0) {print ("test")}
Error: unexpected '=' in "if (aa="
> aa
Error: object 'aa' not found
> if (bb<-0) {print ("test")}
> bb
[1] 0
What in the LOLWTF...This is a bad example because even as an experienced programmer, I have no idea what is supposed to happen, or why this pattern would even be used -- and even then, I was surprised with the result. This is an overly complicated explanation even if it is correct. I prefer Hadley Wickham's style guide:http://adv-r.had.co.nz/Style.html
> Use <-, not =, for assignment.
(an assignment operator that isn't an equals sign is one of the things I miss most when switching away from R)
From the next chapter, Listing Objects: http://www.studytrails.com/R/Core/ListingObjects.jsp
> All entities in R are called objects. They can be arrays, numbers, strings, functions.
This may technically be the case, but any R tutorial that does not open up with what makes R different from other mainstream languages is doing the reader a major disservice. This Listing Objects chapters shows patterns that use R in ways that I haven't seen used in other R examples (beginner and advanced). Even if it's correct, what's the point in showing esoteric examples unless this tutorial is meant to teach R to someone interested in the design of languages?
Again, Wickham's Advanced R book handles this topic well (in fact, Advanced R is probably the best book you can read if you already know how to program -- it is incredibly accessible) in his early chapter on Data structures: http://adv-r.had.co.nz/Data-structures.html
> R’s base data structures can be organised by their dimensionality (1d, 2d, or nd) and whether they’re homogeneous (all contents must be of the same type) or heterogeneous (the contents can be of different types). This gives rise to the five data types most often used in data analysis...Almost all other objects are built upon these foundations. In the OO field guide you’ll see how more complicated objects are built of these simple pieces.
And this next sentence is the one thing I wished someone had printed out and stapled to my forehead before I started to learn R:
> Note that R has no 0-dimensional, or scalar types. Individual numbers or strings, which you might think would be scalars, are actually vectors of length one.
Maybe that's self-evident to other programmers, but even as someone who once programmed in MATLAB, I was stunningly ignorant I was of how every return value I interacted with was a vector, even a single simple string. In retrospect, the interactive shell alludes to this...but I didn't even bother looking up the details about the shell:
> 2 + 2
[1] 4
> 'a'
[1] "a"
R is wonderfully easy to start up with and produce visualizations with. But skipping over the language's fundamentals was incredibly painful for me. A few minutes skimming "Advanced R" would have easily saved me hours of confusion.