First draft of Object-oriented programming in R completed

Writing’s been going very well this week and I have now finished the last two chapters of Object-oriented Programming in R. These chapters cover the S4 and the R6 object systems.

I have uploaded the complete (draft) manuscript to Leanpub now (you can get it for $0.99 + VAT or if you promise to give me feedback I’ll get it to you for free). I will leave it alone for a week or two now so I can read it with fresh eyes when I need to edit it (and I am sure a lot of editing is needed; I have just written it and not actually read it yet).

While this manuscript is resting I will go back to Functional Programming in R. I want to edit it after it has rested a bit and I am thinking of adding a chapter or two but I’ll have to see how that goes. Essentially, I would like to add some algorithmic stuff to it; perhaps some functional data structures and such. I’ll give it a go, at least, and see how it fits in.

If you want both Functional Programming in R and Object-oriented Programming in R really cheap, as in cheaper than the sum of the the minimal prices, you can get them bundled as Advanced Statistical Programming in R. There is only a minimal price of $1.45 (+VAT) and no suggested price, but feel free to increase the price if you want to support me writing these books. I will soon start on a third one to add to the bundle but it costs me $123.75 to put a new book on Leanpub so I would like at least one of the two books to have sold for that much before I put the next one up…

Not that I am loosing money on writing any more. The Data Science book sold enough to pay for the object-oriented programming book, and the books in total have now paid for my writing software and my Grammarly subscription as well. Still, I would like for each book to at least pay for itself. Neither the functional programming nor the object-oriented programming book has reached that point yet.

Not that they necessarily have to, it would be nice if they did but as long as the total royalties can pay for the fee for putting up new books I am okay.

In other news, I also managed to get through editing of my data science book for Apress. The title will be changed to Beginning Data Science in R and I need to come up with a sub-title. Other than that, it is now in the hands of a production editor and if all goes well it will be out around March.

Object-oriented programming in R

I just finished the first chapter of my next book: Object-oriented programming in R. This time I am planning to go through the object-oriented systems in R and write what I can about how to write object-oriented programs in R.

I’ve put the book on Leanpub but to my shock they now require payment for publication there. US $99 + VAT, which is about the same as I have received in royalties from my other two books. If I include my Grammarly subscription in expenses involved in writing books, I am loosing money on this now.

I can only hope that I can actually make that much with sales in the long run. I am not even a third way there with Functional programming in R which has the same length as I aim at for this book. With Introduction to data science and statistical programming with R I’ve sold for just a tad more than $100, but that is a longer book and that was in the first two months of sales. I’m not really selling any copies any longer.

Since it is now actually costing me money to write books I have put a minimum price on the books. I won’t do that for the new book — I don’t think it is fair to charge for a book that isn’t even finished yet — but I have put a minimum price on the other two. It is $0.99+VAT for Functional programming in R and $1.99+VAT for Introduction to data science and statistical programming with R. It is about a third of the recommended price, so it is still pretty cheap, and it might make me enough money that I can afford publishing a fourth book.

More bindr

I extended my new bindr package a little today. If you recall it lets you assign to local variables from return values of functions, so, for example, you can use

f < - function(x, y) list(x = x, y = y)
bind(a, b) %<-% f(2, 3)

to assign to local variables a and b the values returned by the function f.

What I implemented today was a syntax for using variables returned by a function — if it returns a list or vector — in expressions for assigning to the local variables.

So now you can write code like this:

f <- function(x, y) list(x = x, y = y)
bind(a = 2 + x, b = a + 3 + y) %<-% f(2, 3)

You can combine positional arguments and expression like these, but probably shouldn’t. If you do, the position alone determines what you get assigned to, so

f <- function(x, y) list(x = x, y = y)
bind(a = y, b) %<-% f(2, 3)

will assign the value of y, 3, to both a and b.

The implementation is contained in the assignment operator and looks like this:

%<-% < - function(bindings, value) {
  if (length(bindings$bindings) > length(value))
    stop("More variables than values to bind.")
  var_names < - names(bindings$bindings)
  val_names < - names(value)
  has_names <- which(nchar(val_names) > 0)
  value_env <- list2env(as.list(value[has_names]),
                        parent = bindings$scope)
  for (i in seq_along(bindings$bindings)) {
    name <- var_names[i]
    if (length(var_names) == 0 || nchar(name) == 0) {
      # we don't have a name so the expression should be a name
      # and we are going for a positional value
      variable <- bindings$bindings[[i]]
      if (!is.name(variable))
        stop(paste0("Positional variables cannot be expressions ",
                    deparse(variable), "\n"))
      val <- .unpack(value[i])
      assign(as.character(variable), val, envir = bindings$scope)
    } else {
      # if we have a name we also have an expression and we evaluate that
      # in theenvironment of the value followed by the enclosing
      # environment and assign the result to the name.
      val <- eval(bindings$bindings[[i]], value_env)
      assign(name, val, envir = bindings$scope)
    }
  }
}

It is not terribly complicated. The only thing you need to keep track of is the environment in which to evaluate expressions, where I make one for the values given on the right-hand side, chain it with the calling frame (saved in the bind function call), and evaluate the expressions in this.

Fun with non-standard evaluation and binding parameters

I am thinking about examples for something useful but simple that can be done with non-standard evaluation in R for when I, in the far future, get to that book. And preferably something I can find a use for myself so it isn’t just wasted on writing but also helps me in my programming.

One thing I miss in R is assigning to more than one variable in pattern matching, or just for tuples or lists for that matter. So that is something I could start playing with. So I did, and you can see the first result on GitHub.

Right now it is just equivalent to tuple/list assignment in Python where you can assign multiple values like this:

x, y, z = 1, 2, 3

and you can use this for vectors and lists. Nothing fancy with pattern matching at all.

The syntax is inspired by the boost implementation of this in C++ and you use a function bind to specify the variables you want to bind and then an infix operator %< -% to assign to the binding.

bind(x, y, z) %<-% 1:3

I briefly considered overwriting the assignment operator, <-, because I just know that I am likely to write

bind(x, y, z) <- 1:3

in such expressions, but sanity prevailed and I left the assignment operator the way it is. It breaks all kinds of things that I cannot fully understand if I mess with it. So therefore a new infix operator %<-%.

The implementation is pretty simple. I just collect the parameters and the enclosing environment in the bind function and then put values in the environment in the %<-% function.

bind <- function(...) {
  bindings <- eval(substitute(alist(...)))
  scope <- parent.frame()
  structure(list(bindings = bindings, scope = scope), class = "bindings")
}

.unpack < - function(x) UseMethod(".unpack")
.unpack.default <-  function(x) x
.unpack.list <- function(x) x[[1]]
<code>%<-%</code> <- function(bindings, value) {
  if (length(bindings$bindings) > length(value))
    stop("More variables than values to bind.")

for (i in seq_along(bindings$bindings)) {
    variable <- bindings$bindings[[i]]
    val <- .unpack(value[i])
    assign(as.character(variable), val, envir = bindings$scope)
  }
}

(Sorry for the formatting of the %<-% name here, I don’t know why the highlighter absolutely has to replace backticks with code-tags, but it does).

The unpack helper functions are just there so I get the value when I have a list and not a length-one list. Otherwise, there is nothing much to it.

For my next trick, I need to figure out how I can bind variables by accessing the names in a value list.

Filter, Map, and Reduce

Just finished the next chapter in Functional Programming in R. This chapter covers the Filter, Map, and Reduce functions and the family of apply functions and a short introduction to the purrr package.

The chapters seem to be getting a little shorter here towards the end of the book, but there isn’t that much to say about these functions. I will think about it a little and see if I can add a little more, but I don’t feel like padding the chapter just to get its length up to the same size as the previous chapters.

I have thought about how to get the previous chapter a little longer. The continuation-passing-style is not that easy to get around mentally if you haven’t seen it before, so I think I will add another example to that section. I just need a good example to use. Will have to think about that.

Anyway, now that this chapter is drafted I will go back to working on Introduction to Data Science and Statistical Programming in R and get that edited so it is ready when teaching starts in two weeks.