Just for fun I am trying to overload the -
in R so that running
some.string - n
will give me the some.string with the last n characters removed.
This is my code in R
`-` <- function(x,y) {
minus <- force(`-`)
if(typeof(x) == "character" & y >0) {
return(substr(x,1,minus(nchar(x), as.integer(y))))
} else {
return(minus(x,y))
}
}
"abc" - 2
However this seems to cause a an infinitely nested recursion. This is because every time minus is run it tries to run itself. But that's exactly what I am trying to prevent by assigning minus = -
in the first place?
How do I avoid this endless recursion?
Operator Overloading in Binary Operators Here, + is a binary operator that works on the operands num and 9 . When we overload the binary operator for user-defined types by using the code: obj3 = obj1 + obj2; The operator function is called using the obj1 object and obj2 is passed as an argument to the function.
To get cout to accept a Date object after the insertion operator, overload the insertion operator to recognize an ostream object on the left and a Date on the right. The overloaded << operator function must then be declared as a friend of class Date so it can access the private data within a Date object.
Which operator is overloaded by the __or__() function? Explanation: The function __or__() overloads the bitwise OR operator |.
Which of the following operator can be overloaded? c) . Explanation: ?:, :: and . cannot be overloaded whereas == can be overloaded.
Along the lines of suggestion from @PatrickRoocks, make your own (S3 or S4) class and dispatch (rather than mask) on that.
`-.my` = function(e1, e2) substr(e1, 1, nchar(e1) - e2)
x = c('all', 'the', 'world')
class(x) = 'my'
x - 1
## [1] "al" "th" "worl"
## attr(,"class")
## [1] "my"
See also ?Ops in the base (for S3) or methods (S4) package, which defines a 'group generic'
Ops.my = function(e1, e2) {
FUN = get(.Generic, envir = parent.frame(), mode = "function")
substr(e1, 1, FUN(nchar(e1), e2))
}
to implement (in a nonsensical way, for the specific function above -- substr(x, 1, nchar(x) + 2)
doesn't make sense), x - 1
, x + 1
, x / 2
, etc. in a single definition.
The S4 version (sort of like @Sebastian, and from here) is
.My = setClass("My", contains="character")
setMethod("Arith", c("My", "numeric"), function(e1, e2) {
substr(e1, 1, callGeneric(nchar(e1), e2))
})
with
> .My(c("all", "the", "world")) - 1
An object of class "My"
[1] "al" "th" "worl"
Here is another solution using S4 method dispatch. The dispatch will be more elegant compared to using if-else structures and you do not have to mask the primitive function -
. However for primitive functions it appears that it is not allowed to define methods for atomic data types. Hence, I needed to define a new class "lastCharacters". Actually this makes the last line a bit more readible as the intention of the code is clear...
lastCharacters <- setClass("lastCharacters", contains = "numeric")
setMethod("-",
signature(e1 = "character", e2 = "lastCharacters"),
function(e1, e2) {
substr(e1, 1, nchar(e1) - as.integer(e2))
})
"abc" - lastCharacters(2)
You can use .Primitive("-")
to avoid an endless loop. This should work:
`-` <- function(x,y) {
if(typeof(x) == "character" & y >0) {
return(substr(x, 1, nchar(x) - as.integer(y)))
} else {
.Primitive("-")(x, y)
}
}
Closer to your original idea is to define minus <- get("-", envir=baseenv())
:
`-` <- function(x,y) {
minus <- get("-", envir=baseenv())
if(typeof(x) == "character" & y >0) {
return(substr(x,1,minus(nchar(x), as.integer(y))))
} else {
return(minus(x,y))
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With