Define a S3 function using UseMethod [closed] - r

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I am new to the programming R. I defined a function called liw.mstreeClass and I defined as below, but when I run the program I am keep getting the following errors:
# define method: lcosts(generic dispatch)
liw.mstreeClass <- function(nb, data, method, p) UseMethod("nbcosts"){
Error: unexpected '{' in "liw.mstreeClass <- function(nb, data, method, p) UseMethod("nbcosts"){"
if(method=="penrose") { liw <- mat2listw(penroseDis.mstreeClass((scale(data))))
return(liw)}
Error: object 'method' not found
}
Error: unexpected '}' in " }"

# liw.mstreeClass <- function(nb, data, method, p) UseMethod("nbcosts"){
# Error: unexpected '{' in "liw.mstreeClass <- function(nb, data, method, p)
Well, to start with, you've got a syntax error here. You can group several expressions with curly brackets but not start curly brackets after an expression.
Compare...
mean(1)
... with ...
mean(1){
# error!!
Secondly, in S3 you define methods for already existing generic functions. So if you have a function "liw" that could be applied to several classes, then liw.mstreeClass would define the way to do the "liw" for a class called "mstreeClass". So you first have to define liw as a generic function:
liw<-function(x,...){
UseMethod("liw")
}
Notice that you must have "liw" as an argument to UseMethod, not some random crap. (Take a look at the manual to understand why.) You would rarely have a lot of code besides the call to UseMethod in a generic function's body.
And having done that, you can define an mstreeClass method for liw. For example,
liw.mstreeClass<-function(x, y, z){
paste("liw equals ", x + y + z)
}
Note that as method dispatch in S3 is based on the first argument, your x must have class "mstreeClass" - only in that case, liw(x) will be directed to liw.mstreeClass(x). And I think if your generic has x as the first argument then the first argument of all methods must be called x too.
UseMethod("nbcosts"){"
if(method=="penrose") { liw <- mat2listw(penroseDis.mstreeClass((scale(data))))
return(liw)}
Error: object 'method' not found
}
Error: unexpected '}' in " }"
Umm.. sorry, these lines don't make a lot of sense. See above or the manuals on how to use UseMethod.

Related

rlang: Error: Can't convert a function to a string

I created a function to convert a function name to string. Version 1 func_to_string1 works well, but version 2 func_to_string2 doesn't work.
func_to_string1 <- function(fun){
print(rlang::as_string(rlang::enexpr(fun)))
}
func_to_string2 <- function(fun){
is.function(fun)
print(rlang::as_string(rlang::enexpr(fun)))
}
func_to_string1 works:
> func_to_string1(sum)
[1] "sum"
func_to_string2 doesn't work.
> func_to_string2(sum)
Error: Can't convert a primitive function to a string
Call `rlang::last_error()` to see a backtrace
My guess is that by calling the fun before converting it to a string, it gets evaluated inside function and hence throw the error message. But why does this happen since I didn't do any assignments?
My questions are why does it happen and is there a better way to convert function name to string?
Any help is appreciated, thanks!
This isn't a complete answer, but I don't think it fits in a comment.
R has a mechanism called pass-by-promise,
whereby a function's formal arguments are lazy objects (promises) that only get evaluated when they are used.
Even if you didn't perform any assignment,
the call to is.function uses the argument,
so the promise is "replaced" by the result of evaluating it.
Nevertheless, in my opinion, this seems like an inconsistency in rlang*,
especially given cory's answer,
which implies that R can still find the promise object even after a given parameter has been used;
the mechanism to do so might not be part of R's public API though.
*EDIT: see coments.
Regardless, you could treat enexpr/enquo/ensym like base::missing,
in the sense that you should only use them with parameters you haven't used at all in the function's body.
Maybe use this instead?
func_to_string2 <- function(fun){
is.function(fun)
deparse(substitute(fun))
#print(rlang::as_string(rlang::enexpr(fun)))
}
> func_to_string2(sum)
[1] "sum"
This question brings up an interesting point on lazy evaluations.
R arguments are lazily evaluated, meaning the arguments are not evaluated until its required.
This is best understood in the Advanced R book which has the following example,
f <- function(x) {
10
}
f(stop("This is an error!"))
the result is 10, which is surprising because x is never called and hence never evaluated. We can force x to be evaluated by using force()
f <- function(x) {
force(x)
10
}
f(stop("This is an error!"))
This behaves as expected. In fact we dont even need force() (Although it is good to be explicit).
f <- function(x) {
x
10
}
f(stop("This is an error!"))
This what is happening with your call here. The function sum which is a symbol initially is being evaluated with no arguments when is.function() is being called. In fact, even this will fail.
func_to_string2 <- function(fun){
fun
print(rlang::as_string(rlang::ensym(fun)))
}
Overall, I think its best to use enexpr() at the very beginning of the function.
Source:
http://adv-r.had.co.nz/Functions.html

Recursive default argument reference [duplicate]

This question already has an answer here:
Unexpected behaviour with argument defaults
(1 answer)
Closed 5 years ago.
Can anyone explain me what is wrong in this code below. What I thought I am doing here is
a declaration of a global variable a=5
a definition of a function fun which takes one argument which defaults to the aforementioned global variable a
And when I call fun() without any parameters the local variable a becomes a copy of the global variable a and at any point in the function code it takes precedence over the global a (unless I specifically use get("a", envir=parent.frame))
But I must be wrong. Why isn't it allowed?
> a = 5
> fun = function(a=a) { a + 1 }
> fun(4)
[1] 5
> fun()
Error in fun() :
promise already under evaluation: recursive default argument reference or earlier problems?
And when I call fun() without any parameters the local variable a becomes a copy of the global variable a
No: default arguments are evaluated inside the scope of the function. Your code is similar to the following code:
fun = function(a) {
if (missing(a)) a = a
a + 1
}
This makes the scoping clearer and explains why your code doesn’t work.
Note that this is only true for default arguments; arguments that are explicitly passed are (of course) evaluated in the scope of the caller.

Call Refenrence Class function by string [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 9 years ago.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Improve this question
Is there a easy way to call a function of object of a reference class by string like a do.call("...",...) for standard functions in R?
Here's a class and instance
A <- setRefClass("A",
fields=list(x="numeric"),
methods=list(value=function() x))
a <- A(x=10)
A funky way of invoking the value method is
> a[["value"]]
Class method definition for method value()
function ()
x
<environment: 0x123190d0>
suggesting that we could do
> do.call("[[", list(a, "value"))()
[1] 10
This has some pretty weird semantics -- the function returned by do.call seems to be independent of the instance, but actually is defined in the instance' environment
> fun = do.call("[[", list(a, "value"))
> fun
Class method definition for method value()
function ()
x
<environment: 0x1c7064c8>
> a$x=20
> fun()
[1] 20
Also, functions are instantiated in a 'lazy' way, so a[["value"]] only returns a function if it has already been called via a$value(). As discussed on ?setRefClass, I think one can force definition of the method at the time of object initialization with
A <- setRefClass("A",
fields=list(x="numeric"),
methods=list(
initialize=function(...) {
usingMethods("value")
callSuper(...)
},
value=function() x))

Debugging unexpected errors in R -- how can I find where the error occurred?

Sometimes R throws me errors such as
Error in if (ncol(x) != 2) { : argument is of length zero
with no additional information, when I've written no such code. Is there a general way for finding which function in which package causes an error?
Since most packages come compressed, it isn't trivial to grep /usr/lib/R/library.
You can use traceback() to locate where the last error occurred. Usually it will point you to a call you make in your function. Then I typically put browser() at that point, run the function again and see what is going wrong.
For example, here are two functions:
f2 <- function(x)
{
if (x==1) "foo"
}
f <- function(x)
{
f2(x)
}
Note that f2() assumes an argument of length 1. We can misuse f:
> f(NULL)
Error in if (x == 1) "foo" : argument is of length zero
Now we can use traceback() to locate what went wrong:
> traceback()
2: f2(x) at #3
1: f(NULL)
The number means how deep we are in the nested functions. So we see that f calls f2 and that gives an error at line 3. Pretty clear. We could reassign f with browser placed just before the f2 call now to check it's input. browser() simply allows you to stop executing a function and look around in its environment. Similar to debug and debugonce except that you don't have to execute every line up until the point you know something goes wrong.
Just to add to what #SachaEpskamp has already suggested, setting options(error=recover) and options(show.error.locations=TRUE) can be extremely helpful when debugging unfamiliar code. The first causes R to launch a debugging session on error, giving you the option to invoke the browser at any point in the call stack up to that error. The second option will tell R to include the source line number in the error.

Exception handling in R [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 6 years ago.
Improve this question
Does anyone have examples/tutorials of exception handling in R? The official documentation is very terse.
Basically you want to use the tryCatch() function. Look at help("tryCatch") for more details.
Here's a trivial example (keep in mind that you can do whatever you want with an error):
vari <- 1
tryCatch(print("passes"), error = function(e) print(vari), finally=print("finished"))
tryCatch(stop("fails"), error = function(e) print(vari), finally=print("finished"))
Have a look at these related questions:
Equivalent of "throw" in R
catching an error and then branching logic
https://stackoverflow.com/search?q=[r]+trycatch
Besides Shane's answer pointing you to other StackOverflow discussions, you could try a code search feature. This original answer pointed to Google's Code Search has since been discontinued, but you can try
Github search as e.g. in this query for tryCatch in language=R;
Ohloh/Blackduck Code search eg this query for tryCatch in R files
the Debian code search engine on top of the whole Debian archive
Just for the record, there is also try but tryCatch may be preferable. I tried a quick count at Google Code Search but try gets too many false positives for the verb itself -- yet it seems tryCatch is more widely used.
This result from a related google search helped me: http://biocodenv.com/wordpress/?p=15.
for(i in 1:16){
result <- try(nonlinear_modeling(i));
if(class(result) == "try-error") next;
}
The function trycatch() is fairly straight forward, and there are plenty of good tutorials on that. A excellent explanation of error handling in R can be found in Hadley Wickham's book Advanced-R, and what follows is a very basic intro to withCallingHandlers() and withRestarts() in as few words as possible:
Lets say a low level programmer writes a function to calculate the absolute
value. He isn't sure how to calculate it, but knows how to construct an
error and
diligently conveys his naiveté:
low_level_ABS <- function(x){
if(x<0){
#construct an error
negative_value_error <- structure(
# with class `negative_value`
class = c("negative_value","error", "condition"),
list(message = "Not Sure what to with a negative value",
call = sys.call(),
# and include the offending parameter in the error object
x=x))
# raise the error
stop(negative_value_error)
}
cat("Returning from low_level_ABS()\n")
return(x)
}
A mid-level programmer also writes a function to calculate the absolute value, making use of the woefully incomplete low_level_ABS function. He knows that the low level code throws a negative_value
error when the value of x is negative and suggests an solution to the problem, by
establishing a restart which allows users of mid_level_ABS to control the
way in which mid_level_ABS recovers (or doesn't) from a negative_value error.
mid_level_ABS <- function(y){
abs_y <- withRestarts(low_level_ABS(y),
# establish a restart called 'negative_value'
# which returns the negative of it's argument
negative_value_restart=function(z){-z})
cat("Returning from mid_level_ABS()\n")
return(abs_y)
}
Finally, a high level programmer uses the mid_level_ABS function to calculate
the absolute value, and establishes a condition handler which tells the
mid_level_ABS to recover from a negative_value error by using the restart
handler.
high_level_ABS <- function(z){
abs_z <- withCallingHandlers(
# call this function
mid_level_ABS(z) ,
# and if an `error` occurres
error = function(err){
# and the `error` is a `negative_value` error
if(inherits(err,"negative_value")){
# invoke the restart called 'negative_value_restart'
invokeRestart('negative_value_restart',
# and invoke it with this parameter
err$x)
}else{
# otherwise re-raise the error
stop(err)
}
})
cat("Returning from high_level_ABS()\n")
return(abs_z)
}
The point of all this is that by using withRestarts() and withCallingHandlers(), the function
high_level_ABS was able to tell mid_level_ABS how to recover from errors
raised by low_level_ABS error without stopping the execution of
mid_level_ABS, which is something you can't do with tryCatch():
> high_level_ABS(3)
Returning from low_level_ABS()
Returning from mid_level_ABS()
Returning from high_level_ABS()
[1] 3
> high_level_ABS(-3)
Returning from mid_level_ABS()
Returning from high_level_ABS()
[1] 3
In practice, low_level_ABS represents a function that mid_level_ABS calls a
lot (maybe even millions of times), for which the correct method of error
handling may vary by situation, and choice of how to handle specific errors is
left to higher level functions (high_level_ABS).
The restart function is very important in R inherited from Lisp. It is useful if you want to call some function in the loop body and you just want the program to continue if the function call collapses. Try this code:
for (i in 1:20) withRestarts(tryCatch(
if((a <- runif(1))>0.5) print(a) else stop(a),
finally = print("loop body finished!")),
abort = function(){})

Resources