Thanks -- that looks like a reasonable change.  I'll have a more
careful look in the next couple of days and apply if I don't run into
any unexpected issues.

luke

On Thu, 16 Apr 2009, William Dunlap wrote:

A possible fix for this is to filter the 'unsused' list before
printing the error message and replacing the promises with
their PRCODE expressions.

Index: match.c
===================================================================
--- match.c     (revision 48329)
+++ match.c     (working copy)
@@ -355,9 +355,28 @@
            }

        if(last != R_NilValue) {
+            /* show bad arguments in call without evaluating them */
+            SEXP unusedForError = R_NilValue, last = R_NilValue ;
+            for(b=unused ; b!=R_NilValue ; b=CDR(b)) {
+                SEXP tagB = TAG(b) ;
+                SEXP carB = CAR(b) ;
+                if (TYPEOF(carB)==PROMSXP) {
+                    carB = PRCODE(carB) ;
+                }
+                if (last==R_NilValue) {
+                    PROTECT(last = CONS(carB, R_NilValue));
+                    SET_TAG(last, tagB);
+                    unusedForError = last ;
+                } else {
+                    SETCDR(last, CONS(carB, R_NilValue));
+                    last = CDR(last) ;
+                    SET_TAG(last, tagB);
+                }
+            }
            errorcall(R_GlobalContext->call,
                      _("unused argument(s) %s"),
-                     CHAR(STRING_ELT(deparse1line(unused, 0), 0)) + 4);
+                     CHAR(STRING_ELT(deparse1line(unusedForError, 0),
0)) + 4);
+                      /* '+4' is to remove 'list' from
'list(badTag1,...)' */
        }
    }
    UNPROTECT(1);

E.g.,
f<-function(x,y)x+y
f(print(1),y=print(2),x=print(3),stop("oops"))
Error in f(print(1), y = print(2), x = print(3), stop("oops")) :
 unused argument(s) (print(1), stop("oops"))
f(print(1),y=print(2),x=print(3),z=stop("oops"))
Error in f(print(1), y = print(2), x = print(3), z = stop("oops")) :
 unused argument(s) (print(1), z = stop("oops"))
f(print(1),y=print(2),z=print(3),x=stop("oops"))
Error in f(print(1), y = print(2), z = print(3), x = stop("oops")) :
 unused argument(s) (print(1), z = print(3))

These calls used to give:

f(print(1),y=print(2),x=print(3),stop("oops"))
[1] 1
Error in f(print(1), y = print(2), x = print(3), stop("oops")) : oops
f(print(1),y=print(2),x=print(3),z=stop("oops"))
[1] 1
Error in f(print(1), y = print(2), x = print(3), z = stop("oops")) :
oops
f(print(1),y=print(2),z=print(3),x=stop("oops"))
[1] 1
[1] 3
Error in f(print(1), y = print(2), z = print(3), x = stop("oops")) :
 unused argument(s) (1, z = 3)

Bill Dunlap
TIBCO Software Inc - Spotfire Division
wdunlap tibco.com

-----Original Message-----
From: r-devel-boun...@r-project.org
[mailto:r-devel-boun...@r-project.org] On Behalf Of William Dunlap
Sent: Thursday, April 16, 2009 10:05 AM
To: l...@stat.uiowa.edu
Cc: r-devel@r-project.org; Dirk Eddelbuettel
Subject: Re: [Rd] How can I catch errors thrown from c via
the Rcpperror()function?

-----Original Message-----
From: l...@stat.uiowa.edu [mailto:l...@stat.uiowa.edu]
Sent: Thursday, April 16, 2009 9:27 AM
To: William Dunlap
Cc: Dirk Eddelbuettel; Kieran O'Neill; r-devel@r-project.org
Subject: Re: [Rd] How can I catch errors thrown from c via
the Rcpperror() function?

Something seems amiss in the process of generating the errormessage:

f <- function(x){}
f(y = print("foo"))
[1] "foo"
Error in f(y = print("foo")) : unused argument(s) (y = "foo")

The argument seems to be getting evaluated and its value is
being used.

luke

It is in match.c, where errorcall() calls deparse1line(unused,0)
to get the name (and value) of the argument:

    357         if(last != R_NilValue) {
    358             errorcall(R_GlobalContext->call,
    359                       _("unused argument(s) %s"),
    360                       CHAR(STRING_ELT(deparse1line(unused, 0),
0)) + 4);

Before deparse1line is called unused is (in my example)
    (gdb) call Rf_PrintValue(unused)
    $badTag
    <promise: 0x9aff4d4>
and deparse1line must be evaluating the promise.  Just showing the
bad tag's name would suffice in the error message, if it is a problem
jury rigging deparse1line to avoid the evaluation in this case.


On Thu, 16 Apr 2009, William Dunlap wrote:

Note that Kieren's example labelled the first
argument to try() with an improper label res30=,
not expr= (or is that a mailer turning something
into '30='?).  If it really is an improper argument
tag then this could be showing a buglet in reporting
on wrongly named arguments:

> invisible(rm(x,y))
> x<-try(silent=TRUE, badTag=stop("Oops"))
 Error in try(silent = TRUE, badTag = stop("Oops")) : Oops
> x
 Error: object "x" not found
> y<-try(silent=TRUE, expr=stop("Oops"))
> y
 [1] "Error in try(silent = TRUE, expr = stop(\"Oops\")) : Oops\n"
 attr(,"class")
 [1] "try-error"

In the first example I would expect an error message like
  unused argument(s) (badTag = stop("Oops"))
but it is appropriate that try() would abort if it
is called in a bad way.  Perhaps it is trying to make that
error message and that triggered the evaluation of the argument,
as in
 > grep(mypattern=stop("Oops"), "wxyz")
  Error in grep(mypattern = stop("Oops"), "wxyz") : Oops
where one might expect an error message regarding the wrongly
named argument, as in:
 > grep(mypattern="x", "wxyz")
  Error in grep(mypattern = "x", "wxyz") :
    unused argument(s) (mypattern = "x")

Bill Dunlap
TIBCO Software Inc - Spotfire Division
wdunlap tibco.com

-----Original Message-----
From: r-devel-boun...@r-project.org
[mailto:r-devel-boun...@r-project.org] On Behalf Of Dirk
Eddelbuettel
Sent: Wednesday, April 15, 2009 7:14 PM
To: Kieran O'Neill
Cc: r-devel@r-project.org
Subject: Re: [Rd] How can I catch errors thrown from c via
the Rcpperror() function?


Kieran,

On 15 April 2009 at 18:03, Kieran O'Neill wrote:
| I am using the flowClust package from BioConductor, which
is largely
| implemented in c. For some of my data, the package
occasionally (and
| quite stochastically) encounters a particular condition
which halts its
| operation. At this point, it calls the error() function
defined by Rcpp,
| and halts.
|
| What I would like to be able to do is to catch the error
thrown, and
| retry the operation a few times before giving up.
|
| However, when I wrap the call to flowClust in try() or
tryCatch(), the
| error seems to completely bypass them:
|
| Examples:
|
| 1. This is a trivial example just to test the try()
function, and
| correctly assigns the error to the variable x:
|
|  > x <- try(stop(simpleError('blah')))
| Error : blah
|  > x
| [1] "Error : blah\n"
| attr(,"class")
| [1] "try-error"
|
| 2. This is an example using flowClust (using real
data, set up to
| guarantee that the error is thrown):
|
|  > x <- try(res30 = flowClust(tFrame, K=30, B=1000,
varNames=c('CD4',
| 'CD8','KI67', 'CD45RO', 'CD28', 'CD57', 'CCR5', 'CD19',
'CD27', 'CCR7',
| 'CD127')))
| Error in flowClust(tFrame, K = 30, B = 1000, varNames =
c("CD4", "CD8",  :
|
| The covariance matrix is near singular!
| Try running the program with a different initial
configuration or less
| clusters
|  > x
| Error: object "x" not found
|
|
| The c code throwing the error is as follows (from flowClust.c):
|
| if(status!=0)
|    {
|        error("\n The covariance matrix is near singular! \n
Try running
| the program with a different initial configuration or
less clusters
| \n");          }
|
|
| I looked up the error() function in Writing R Extensions
and it states:
| "The basic error handling routines are the equivalents
of stop and
| warning in R code, and use the same interface."
|
| Yet, it seems that they are not caught by R's error
handling code.
|
| So:
|
| 1. Is this the general case (that Rcpp error()s are not
handled by try()
| and related methods in R)? (I'm sure this could be tested
with a trivial
| example, but I'm not yet familiar enough with wrapping c
code in R to do
| so.)

Allow me to take the narrow view here as Rcpp maintainer.
What you can do
with Rcpp is to provide a C++ layer of try/catch around inner
code which may
throw C++ exception.  This will usually be caught, and (as
shown in the Rcpp
docs and examples) we can pass the exception message back
up to R as a
regular error message.  This is very useful as it gives you
control back at
the R prompt rather than just going belly-up.

Now, R's try() and tryCatch() are completely separate and not
tied into the
exception mechanism Rcpp deals with, which is at a much
lower level.

Likewise, you may be out of luck with flowClust if it is C
program.  You
could try to add a C++ layer that tried to catch error and
allows you do
continue your loops.  I did something like that 15 years
ago in my
dissertation research to ensure I survived the occassional
numerical error
from Fortran during longer Monte Carlo runs,

| 2. If so, what is the correct way to handle them in R?

Tricky. See 1. :)

| 3. If not, do you have any suggestions as to what may
have caused
| flowClust to behave in this way? (So that I can contact
the package
| maintainers and report the bug.)

You could always contact them anyway and ask for advice.

Hth,  Dirk

--
Three out of two people have difficulties with fractions.

______________________________________________
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


______________________________________________
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


--
Luke Tierney
Chair, Statistics and Actuarial Science
Ralph E. Wareham Professor of Mathematical Sciences
University of Iowa                  Phone:             319-335-3386
Department of Statistics and        Fax:               319-335-3017
    Actuarial Science
241 Schaeffer Hall                  email:      l...@stat.uiowa.edu
Iowa City, IA 52242                 WWW:  http://www.stat.uiowa.edu


______________________________________________
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel



--
Luke Tierney
Chair, Statistics and Actuarial Science
Ralph E. Wareham Professor of Mathematical Sciences
University of Iowa                  Phone:             319-335-3386
Department of Statistics and        Fax:               319-335-3017
   Actuarial Science
241 Schaeffer Hall                  email:      l...@stat.uiowa.edu
Iowa City, IA 52242                 WWW:  http://www.stat.uiowa.edu

______________________________________________
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel

Reply via email to