In R, programmers can create their own operators using the form %x%
where x
is the choice of the programmer. However, you can actually overwrite a native operator:
`*` = function(e1, e2)e1/e2
2*4
[1] 0.5
We have recently seen a new R package called magrittr which made us laugh but also reminded us that operators in R are very useful and fun. So we decided to do a quick blog post writing one package in one line. Please note that this is slightly tongue-in-cheek, magrittr does have a few other features that you should check out. The code for this blog post is at github.
You can create an operator using the backtick operator to define your function, so without futher ado here is magrittr in one line:
`%>%` = function(x, FUN)FUN(x)
That’s it! Now for a quick demo:
iris %>% head
# Sepal.Length Sepal.Width Petal.Length Petal.Width Species
# 1 5.1 3.5 1.4 0.2 setosa
# 2 4.9 3.0 1.4 0.2 setosa
# 3 4.7 3.2 1.3 0.2 setosa
# 4 4.6 3.1 1.5 0.2 setosa
# 5 5.0 3.6 1.4 0.2 setosa
# 6 5.4 3.9 1.7 0.4 setosa
1E4 %>% rnorm %>% hist
As it happens you can also define the operator using either an apostrophe or a speech marks:
# Speech marks
"%>%" = function(x, FUN)FUN(x)
# Apostrophe
"%>%" = function(x, FUN)FUN(x)
Any three of the above implementations will do.
We can’t leave without our own suggestion to the operator collection. In languages like Python, the "+"
operator is used to concatenate strings. So what about something like this: %+%
. Here is the code, again it is one line:
`%+%` = function(x1, x2)paste0(x1, x2)
Here is an example:
"Hello " %+% "World" %+% "! Goodbye " %+% "World!"
[1] "Hello World! Goodbye World!"
We can take this futher and attempt to define a true "+"
operator for character
classes in R, however we run into a brick wall:
setMethod("+", c("character", "character"), function(e1, e2)paste0(e1, e2))
# Error in setMethod("+", c("character", "character"), function(e1, e2) paste0(e1, :
# the method for function ‘+’ and signature e1="character", e2="character" is sealed and cannot be re-defined
A poor substitute is to define this for another class:
# A quick hack:
# Create a new class
setClass("string", "character")
# Set a method for the class
setMethod("+", c("string", "string"), function(e1, e2){
x = paste0(e1, e2); class(x) <- "string"
return(x)
})
# Demo the class
a = new("string", "Hello ")
b = new("string", " World!")
cc = new("string", " Goodbye ")
d = new("string", "World!")
a + b + cc + d
[1] "Hello World! Goodbye World!"
attr(,"class")
[1] "string"
For obvious reasons this is much less desireble than being able to use the "+"
operator on character
classes.
Operators in R are fun. They can be very useful and chaining is one such useful attribute.