[R] get caller's name

William Dunlap wdunlap at tibco.com
Fri Feb 4 17:09:25 CET 2011


> -----Original Message-----
> From: r-help-bounces at r-project.org 
> [mailto:r-help-bounces at r-project.org] On Behalf Of Duncan Murdoch
> Sent: Friday, February 04, 2011 6:03 AM
> To: Ernest Adrogué
> Cc: r-help at stat.math.ethz.ch
> Subject: Re: [R] get caller's name
> 
> On 03/02/2011 10:27 AM, Ernest Adrogué wrote:
> > Hi,
> > Suppose a function that checks an object:
> >
> > stop.if.dims<- function(x) {
> >    if (! is.null(dim(x))) {
> >      stop("cannot handle dimensional data")
> >    }
> > }
> >
> > This would be used by other functions that can only work with
> > dimensionless objects. The problem is the error message 
> would need to
> > include the name of the function that called stop.if.dims, 
> so that the
> > user knows which function got an argument that was incorrect.
> >
> > How do I do this? Or maybe there is another way...
> 
> I see you have the answer you wanted, but I'd suggest you don't need 
> this:  the user should just use traceback() after the error 
> to see the 
> full call stack.  Perhaps it's not the caller that's the problem, but 
> the caller of the caller...
> 
> Duncan Murdoch

stopifnot() deals with the problem by arranging for the
error reporting mechanism not to say what function the
error comes from.  If you are in the know, not seeing
"Error in someFunction(arg):" in the error might motivate
you to call traceback().  If you are not in the know, it
just frustrates you.

   R> myFunc <- function(x) stopifnot(all(x>0))
   R> myFunc(-pi)
   Error: all(x > 0) is not TRUE
   R> traceback()
   3: stop(paste(ch, " is not ", if (length(r) > 1L) "all ", "TRUE", 
          sep = ""), call. = FALSE)
   2: stopifnot(all(x > 0))
   1: myFunc(-pi)

In S+ stopifnot() uses eval(call("stop", message), sys.parent())
to make the error message appear to come from the caller of
stopifnot().  The initial message is clearer but the traceback
more confusing:

   > myFunc <- function(x) stopifnot(all(x>0))
   > myFunc(-pi)
   Problem in myFunc( - pi): all(x > 0) is not TRUE 
   Use traceback() to see the call stack
   > traceback()
   8: eval(action, sys.parent())
   7: doErrorAction("Problem in myFunc( - pi): all(x > 0) is not TRUE", 1000)
   6: stop("all(x > 0) is not TRUE")
   5: eval(call, sys.parent())
   4: stopifnot(all(x > 0))
   3: myFunc( - pi)
   2: eval(expression(myFunc( - pi)))
   1: 
   Message: Problem in myFunc( - pi): all(x > 0) is not TRUE 

If I try the eval(call("stop",message), sys.parent()) trick
in R the error is reported as being from eval():
   > myFunc(-pi)
   Error in eval(expr, envir, enclos) : all(x > 0) is not TRUE

S+'s error handler has some logic so that a stop() called from
eval() is reported as being from the frame that eval is evaluating
in.

It might be nice to be able to tell stop(), warning(), and message()
to pretend they were called from somewhere other than where they
were actually called from.  Falling back on traceback() doesn't
help with warnings and messages.  Being able to put standard messages
like 'x not a matrix' into utility functions is handy, but it makes
it hard to track down the problem.

Bill Dunlap
Spotfire, TIBCO Software
wdunlap tibco.com 


> 
> ______________________________________________
> R-help at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide 
> http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.
> 



More information about the R-help mailing list