Skip to main content

·3 mins

Function results can’t be assigned to #

Let’s say we have a “normal” programming language such as Python:

def foo(a, b):
	return a + b

foo(1, 2) = 10 # <- This is obviously not true

In my mental model, foo(1, 2) evaluates to 3 first. Therefore, the line in question is the same as 3 = 10, which doesn’t work. More generally, we assume that only variables (or attributes, which are differently scoped variables) can be assigned to.

That’s why it’s so surprising to me when I see this code in an tutorial:

seqlengths(gr) <- c(249250621,243199373,198022430)

This is just strange. I’ve never seen a language where something that’s not obviously a variable can be mutated via assignment. In R, however, functions have have various forms. One of these forms is an assignment form. To quote the R manual:

A special type of function calls can appear on the left hand side of the assignment operator as in r class(x) <- "foo"

What this construction really does is to call the function class<- with the original object and the right hand side. This function performs the modification of the object and returns the result which is then stored back into the original variable. (At least conceptually, this is what happens. Some additional effort is made to avoid unnecessary data duplication.)

To elaborate, it explains:

The replacement function has the same name with <- pasted on. Its last argument, which must be called value, is the new value to be assigned. For example,

names(x) <- c(“a”,“b”)

is equivalent to

`*tmp*` <- x
x <- "names<-"(`*tmp*`, value=c("a","b"))
rm(`*tmp*`)

This almost makes sense to me. It’s essentially saying something like this in Python:

# this invalid call
last_name(Benjamin) = "Lee"

# gets translated to
tmp = Benjamin
Benjamin = with_last_name(tmp, "Lee")

What stops making sense is the inconsistent use of backticks and quotation marks in escaping names.

Backticks and quotes for name escaping #

While the use of backticks for name escapign might be unexpected to Python programmers, it’s normal in Nim. Say you want to define an overload for $, the stringification function in Nim. You can’t directly assign to that symbol (since it’s not an otherwise valid variable name) so you escape it using backticks. In the R example, you used backticks to escape the name *tmp* since it wouldn’t be valid. Ok so far but perhaps a surprising to some.

What goes off the hinges is that you can also use quotes to do escaping sometimes. As pointed out on Stack Overflow, it creates really weird outcomes like this:

> a <- 1:3
> "a[1]" <- 55
> a[1]
[1] 1
> "a[1]"
[1] "a[1]"
> `a[1]`
[1] 55

Here, you can use quotes for assignment to an otherwise illegal name but not for accessing it.

Benjamin D. Lee
Author
Benjamin D. Lee
Benjamin D. Lee is an NIH-OxCam scholar pursuing his doctorate at Oxford University. His research is focused on the computational identification and analysis of novel viruses and virus-like agents to better understand their evolution and origin.