double NextMethod() in r - r

I am having problems how to make the following code work. In particular what should I have in the place of '???' to obtain the result c(4,7,1)
letter<- function()
{
x<- numeric(0)
class(x)<- append(class(x), "letter")
return(x)
}
a<- function()
{
obj<- letter()
class(obj)<- append(class(obj),"a")
return(obj)
}
aa<- function()
{
obj<- a()
class(obj)<- append(class(obj),"aa")
return(obj)
}
met<- function(obj, ...)
{
UseMethod("met", obj)
}
met.letter<- function(obj, ???)
{
NextMethod(???)
}
met.a<- function(obj, ???)
{
x<-4
z<-1
NextMethod(???)
}
met.aa<- function(obj, ???)
{
y=y+1
return(c(x,y,z))
}
aaobj<- aa()
met(aaobj, y=6)
# to return c(4,7,1)
I can not understand how to pass arguments to the next method, when they are created in the current method, and I don't want to pass these arguments to the call to the method.

Here is an OO-alike version of your code with "log output" to indicate how it works:
# Class Hierarchy:
# AA inherits from A inherits from letter (= base class)
# Constructors ---------------------------------------------
letter <- function()
{
x <- numeric(0) # this shall be an class attribute
class(x) <- append("letter", class(x))
return(x)
}
a <- function() # class "a" inherits from class "letter"
{
obj <- letter()
class(obj) <- append("a", class(obj)) # attach the specialized class first!
return(obj)
}
aa <- function() # class "aa" inherits from class "a"
{
obj <- a()
class(obj) <- append("aa", class(obj))
return(obj)
}
# Class methods -------------------------------------------
# This is a function in the base class "letter" that is inherited in the sub classes
# so that every sub class can provide its own implementation (polymorphism).
# To register such a generic function (= function call dispatching to class-specific functions/methods)
# "UseMethod" is called
met <- function(obj, x) # met = method?!
{
UseMethod("met", obj) # "dispatch": Call the first existing function of pattern "met.<class>"
# Code after this line will never be executed due to calling "UseMethod"
print("met")
}
met.aa <- function(obj, x)
{
print("met.aa - starting")
x = x + 1
NextMethod("met", obj) # as last code in the function: Returns the return value of this function!
# Do not add code after "NextMethod" or you will get the output of this code as return value
# instead of the return value of NextMethod!
# print("met.aa - leaving")
}
met.a <- function(obj, x)
{
print("met.a - starting")
x <- c(4, x, 1)
res <- NextMethod("met", obj) # , c(4, x, 1))
print("met.a - leaving") #
return(res)
}
met.letter<- function(obj, x) # x may be a vector!
{
print("met.letter starting")
# "append" looses the attributes (class!) so we reassign it
# a() should better return a list with one vector element as "class attribute"
# so that the attributes keep untouched if changing the "class attribute"
old.classes <- class(obj)
obj <- append(obj, x)
class(obj) <- old.classes
# no NextMethod() call - it is the base class (= root!)
return(obj)
}
met.default <- function(obj, x) {
warning("met.default: not implemented")
}
aaobj <- aa()
aaobj
# numeric(0)
# attr(,"class")
# [1] "aa" "a" "letter" "numeric"
aaobj <- met(aaobj, 6)
aaobj
# [1] 4 7 1
Note: You should put your class name at the beginning (not the end) of the class attribute so that if you call a generic method the most specialized class method will be found and called first.
For details see http://www.stackoverflow.com/q/45175988

Related

How to make a generic R function inherit the class of its input?

Let the following code:
x <- 1:5
class(x) <- "bar"
foo <- function(x) {
UseMethod("foo")
}
foo.bar <- function(x) {
y <- max(x)
return(y)
}
I would like the output of foo(x) to have the same class as x (i.e., "bar"). The obvious way to do it is to add a class(y) <- class(x) inside foo.bar(), but I would like to know if/how I could do that in foo() itself.
The reason for this is that my real case has several generics, each one with 10+ methods, so if I could inherit the class in the generics, I'd just have to modify those instead of tens of methods.
Rename foo to foo_, say, and then define foo to call foo_ and then set the class.
foo_ <- foo
foo <- function(x) structure(foo_(x), class = class(x))
foo(x)
giving:
[1] 5
attr(,"class")
[1] "bar"

How can I change the behavior of the $ operator in environments?

I want to override the behavior of the dollar operator, so that if I have
x <- new.env()
x$foo <- 3
will e.g. call something. I tried to look for possible functions such as $, but my knowledge of the internals is not good enough.
I tried this:
`$` <- function(a, b) {
res <- .Primitive("$")(a, b);
print(res);
if(is.null(res)) { print("null!") };
return(res)
}
It kind of seem to work, but:
> x$foobar
NULL
[1] "null!"
NULL
> x$foobar <- 3
> x$foobar
NULL
[1] "null!"
NULL
>
So it seems to stay null despite the override.
Normal behavior of R's environments:
myenv <- new.env(parent = emptyenv())
myenv$foo <- 3
class(myenv)
# [1] "environment"
myenv$foo
# [1] 3
myenv$foobar
# NULL
Let's define a super-class (I'll name it environment2, feel free to be creative here) and override $ for that class:
class(myenv) <- c("environment2", "environment")
`$.environment2` <- function(x, name) {
stopifnot(name %in% names(x))
NextMethod()
}
myenv$foo
# [1] 3
myenv$foobar
# Error in `$.environment2`(myenv, foobar) : name %in% names(x) is not TRUE
You can easily clean up that error if you'd like, either using an if statement with stop, or (in R-4 or newer) naming the conditions in stopifnot.
`$.environment2` <- function(x, name) {
if (!name %in% names(x)) stop("something meaningful", call. = FALSE)
NextMethod()
}
`$.environment2` <- function(x, name) {
stopifnot(
"something meaningful" = name %in% names(x)
)
NextMethod()
}
### both render
myenv$foobar
# Error in `$.environment2`(myenv, foobar) : something meaningful
They are relatively equivalent, but with if/stop, you can reduce the error context:
`$.environment2` <- function(x, name) {
if (!name %in% names(x)) stop("something meaningful", call. = FALSE)
NextMethod()
}
myenv$foobar
# Error: something meaningful

In R, modify a value within a class

Maybe I am thinking of R classes as if they were classes in C or Java, but I cannot seem to modify values:
test <- function() {
inc <- function() {
x <- attr( obj, "x" )
x <- x + 1
print(x)
attr( obj, "x" ) <- x
return( obj )
}
obj <- list(inc=inc)
attr( obj, "x" ) <- 1
class(obj) <- c('test')
return( obj )
}
When I run this:
> t <- test()
> t <- t$inc()
[1] 2
> t <- t$inc()
[1] 2
It is as if the original class object cannot be modified.
One can use the lexical scoping mechanism of R to achieve a C or Java like object orientation.
Use <<- to assign a value in the parent environment.
A simplified version of your examples is below.
test <- function() {
inc <- function() {
x <<- x + 1
print(x)
}
x <- 1
list(inc=inc)
}
obj <- test()
obj$inc()
[1] 2
obj$inc()
[1] 3
See also ?refClass-class for what is called "reference classes" in R.

R get object from global environment from function if object exists in global but use different default if not

Surely this is possible, but I can't seem to find how to do it:
I'd like to have a default of a function input, but override the default and get() a variable from the global environment if it exists in the global environment. If it doesn't exist in the global environment, take the default of the function, with any setting in the function being top level and overriding them all.
Ideally it would work like this made-up non-working function:
###Does not work, desired example
myfunc <- function(x=30){
if(exists.in.global.env(x)){x <- get(x)}
###Top level is tough
if(x.is.defined.as.function.input=TRUE ????){x <- x.defined.as.input}
}else{ x <- 30}
return(x)
}
So that if I do:
myfunc()
[1] 30
But if I create x I want it to override the default x=30 of the function and take the global environment value instead:
x <- 100
myfunc()
[1] 100
But if I have x defined inside the function, I'd like that to be top level, i.e. override everything else even if x is defined globally:
x <- 100
myfunc(x=300)
[1] 300
Thanks in advance!
You can modify your function to check if x exists in the .GlobalEnv and get it from there if it does, otherwise return the default value.
myfunc <- function(x = 30) {
if ("x" %in% ls(envir = .GlobalEnv)) {
get("x", envir = .GlobalEnv)
} else {
x
}
}
So if "x" %in% ls(envir = .GlobalEnv) is FALSE it would return
myfunc()
[1] 30
If x is found it would return it. if x <- 100:
myfunc()
[1] 100
Edit after comment
If you want to make sure to only return x from the global environment if x is not specified as an argument to myfunc, you can use missing(). It returns TRUE if x was not passed and FALSE if it was:
myfunc <- function(x = 30) {
if ("x" %in% ls(envir = .GlobalEnv) & missing(x)) {
get("x", envir = .GlobalEnv)
} else {
x
}
}
So for your example:
x <- 100
myfunc(x=300)
[1] 300
The simplest method would be to set an appropriate default argument:
myfunc <- function(x=get("x", globalenv())
{
x
}
> x <- 100
> f()
[1] 100
> f(30)
[1] 30
> rm(x)
> f()
Error in get("x", globalenv()) : object 'x' not found

R: Storing function symbols for later reuse and making a global "undebug()"

I would like to write a wrapper for the debug() function so that I can remove all debugging flag when needed.
For functions in the search path it is simple.
.debugged <- NULL
debug.wrapper <- function(fun){
f <- deparse(substitute(fun))
.debugged <<- unique(c(.debugged, f))
debug(f)
}
debug.wrapper.off <- function() {
z=sapply(.debugged, undebug)
.debugged <<- NULL
}
It works because I can use the character version of the function symbol.
f <- function() print("hello")
debug.wrapper(f)
isdebugged(f)
# [1] TRUE
debug.wrapper.off()
isdebugged(f)
# [1] FALSE
Anyway with namespaces it does not work:
debug.wrapper(tools:::psnice)
# Error in debug(f) could not find function "tools:::psnice"
Also:
debug(substitute(tools:::psnice))
# Error in debug(fun, text, condition) : argument must be a function
How can I store the function symbols for later reuse?
Note
It seems that concatenating function symbols creates a sort of "soft pointer" rather than a copy, that is:
x <- c(tools:::psnice, identity)
Taking the first function, we get:
x[[1]]
# function (pid = Sys.getpid(), value = NA_integer_)
# {
# res <- .Call(ps_priority, pid, value)
# if (is.na(value))
# res
# else invisible(res)
# }
# <bytecode: 0x00000000189f1f80>
# <environment: namespace:tools>
The bytecode and environment are the same as with tools:::psnice.
Therefore un/debug(x[[1]]) is like un/debug(tools:::psnice)
Solution
Given the note above, the solution is trivial. Debug wrappers are defined as:
.debugged <- NULL
debug.wrapper <- function(fun){
.debugged <<- unique(c(.debugged, fun))
debug(fun)
}
debug.wrapper.off <- function() {
z=sapply(.debugged, undebug)
.debugged <<- NULL
}
Using them brings:
f <- function() print("hello")
debug.wrapper(f)
debug.wrapper(tools:::psnice)
isdebugged(f)
# [1] TRUE
isdebugged(tools:::psnice)
# [1] TRUE
debug.wrapper.off()
isdebugged(f)
isdebugged(tools:::psnice)
.debugged
# NULL
Of course, one can add conditions to manage the case when passed fun is a string.
Thanks to #Rich Scriven, who gave useful insights.

Resources