tl;dr
I present you a function that warns if an R script contains the Assignment Operator That Shall Not Be Named.
Assign of the times
So, it’s been confirmed with extremely robust and objective evidence: the left-assignment arrow (x <- 1
) is better than equals (x = 1
) for assignment in R.1
So, unless you hate democracy, you should protect yourself from aberrant code that uses the cursed symbol.
But what if a nefarious colleague still sends you their scuffed code?
Assignment refinement
I’ve created the appraise_assignment()
function that will peek at a suspect script and warn you if it contains the foul mark.
appraise_assignment <- function(file, destroy = FALSE) {
trees <- lintr::get_source_expressions(file) # parse code
expr_len <- length(trees[[1]]) # we want the final element
tokens <- # extract tokens used in script
trees$expressions[[expr_len]]$full_parsed_content[, "token"]
if (any(tokens == "EQ_ASSIGN")) { # '='
warning("\nme = 'disgusted'\n")
if (destroy == TRUE) {
answer <- readlines("Destroy file? y/n")
if (answer == "y") cat("Have mercy! This time...")
}
} else if (any(tokens == "RIGHT_ASSIGN")) { # '<-'
cat("'unorthodox' -> you\n")
} else if (any(tokens == "LEFT_ASSIGN")) { # '->'
cat("you <- 'hero'\n")
} else {
cat("anyway(assignment(is(even('what'))))\n")
}
}
It uses Jim Hester’s {lintr} package to parse R expressions and identify each ‘token’ that’s used (maths symbols, special operators, variables, etc).
In particular, it spots the token called EQ_ASSIGN
, which is when =
is used in the context of assignment.
I saw the assign
For demonstration purposes, I’ve written four temporary files containing left assign (<-
), right assign (->
, inferior mirror-copy of <-
), equals (=
), and no assignment at all.2 Our function will catch even a single deviation, even if proper assignment has also been used.
temp <- tempdir() # temp location to store files
purrr::walk2(
c("x <- 1", "x <- 1; y -> 1", "x <- 1; y = 1", "x"),
c("left", "right", "equals", "none"),
~writeLines(.x, file.path(temp, paste0(.y, ".R")))
)
First, let’s pass the file containing the unquestionably correct assignment operator.
appraise_assignment(file.path(temp, "left.R"))
## you <- 'hero'
Right-assignment is left-assignment’s less-handsome sibling.
appraise_assignment(file.path(temp, "right.R"))
## 'unorthodox' -> you
Hold steady…
appraise_assignment(file.path(temp, "equals.R"))
## Warning in appraise_assignment(file.path(temp, "equals.R")):
## me = 'disgusted'
Phew, we got a warning, so we know the file is dangerous and should never be opened.
In fact, if you set the argument destroy = TRUE
in appraise_assignment()
, you’ll be prompted to irrecoverably annihilate the rotten file forever.3
For completeness, is it really an R script if it doesn’t contain any assignment at all?
appraise_assignment(file.path(temp, "none.R"))
## anyway(assignment(is(even('what'))))
Assigning off
In conclusion, some assignment operators were created more equal than others. See Colin Fay’s round-up to learn more about the history and plethora of these symbols (and be happy that the underscore is no longer legitimate).
Anyway, welcome to the best timeline, where we all recognise <-
unequivocally as the champion and =
can get absolutely rekt.
If I had one wish though, it would be to make the left-assign arrow even more powerful. How about making it really long? 23 hyphens seems sufficiently dominant.
x <----------------------- 1
x
## [1] 1
It’s a really long arrow, so I call it ‘the spear’.4 I look forward to its adoption by R Core.
Actually, I don’t really care which one you use, but that’s less of a funny take. I prefer the left assignment operator because look! It’s a little arrow! Quirky! Esoteric! An extra keystroke to exercise your fingers!↩︎
We do not talk about
<<-
.↩︎Well, not really, because I don’t want you to delete any of your files. But rest assured I’ve included
file.remove()
in my local version of the function and I’m not afraid to use it.↩︎If you’re wondering how this works, R evaluates this as
<-
and then a whole bunch of ‘negative’ symbols. They cancel out If you have an odd number of them.↩︎