# Re: stopifnot

6 messages
Open this post in threaded view
|

## Re: stopifnot

Open this post in threaded view
|

## Re: stopifnot -- eval(*) inside for()

 >>>>> Suharto Anggono Suharto Anggono via R-devel >>>>>     on Sun, 31 Mar 2019 15:26:13 +0000 writes:     > Ah, with R 3.5.0 or R 3.4.2, but not with R 3.3.1, 'eval'     > inside 'for' makes compiled version behave like     > non-compiled version. Ah.. ... thank you for detecting that  " eval() inside for()" behaves specially  in how error message get a call or not. Let's focus only on this issue here. I'm adding a 0-th case to make even clearer what you are saying:   >  options(error = expression(NULL))   >  library(compiler)   >  enableJIT(0)   > f0 <- function(x) { x ; x^2 } ; f0(is.numeric(y))   Error in f0(is.numeric(y)) (from #1) : object 'y' not found   > (function(x) { x ; x^2 })(is.numeric(y))   Error in (function(x) { (from #1) : object 'y' not found   > f0c <- cmpfun(f0) ; f0c(is.numeric(y)) so by default, not only the error message but the originating call is shown as well. However, here's your revealing examples:   > f <- function(x) for (i in 1) {x; eval(expression(i))}   > f(is.numeric(y))   > # Error: object 'y' not found   > fc <- cmpfun(f)   > fc(is.numeric(y))   > # Error: object 'y' not found I've tried more examples and did not find any difference between simple interpreted and bytecompiled code {apart from "keep.source=TRUE" keeping source, sometimes visible}. So I don't understand yet why you think the byte compiler plays a role. Rather the crucial difference seems  the error happens inside a loop which contains an explicit eval(.), and that eval() may even be entirely unrelated to the statement in which the error happens [above: The error happens when the promise 'x' is evaluated, *before* eval() is called at all].     > Is this accidental feature going to be relied upon?     [i.e.  *in  stopifnot() R code (which in R-devel and R 3.5.x has             had an eval() inside the for()-loop)] That is a good question. What I really like about the R-devel case:  We do get errors signalled that do *not* contain the full stopifnot() call. With the newish introduction of the exprs = { ... ... } variant, it is even more natural to have large exprs in a stopifnot() call, and when there's one accidental error in there, it's quite unhelpful to see the full stopifnot(..........) call {many lines of R code} obfuscating the one statement which produced the error. So it seems I am asking for a new feature in R, namely to temporarily say: Set the call to errors to NULL "in the following". In R 3.5.x, I had used withCallingHandlers(...) to achieve that and do even similar for warnings... but needed to that for every expression and hence inside the for loop  and the consequence was a relatively large slowdown of stopifnot()..  which triggered all the changes since. Whereas what we see here ["eval() inside for()"] is a cheap automatic suppression of 'call' for the "internal errors", i.e., those we don't trigger ourselves via stop(simplError(...)). ______________________________________________ [hidden email] mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Open this post in threaded view
|

## Re: [External] Re: stopifnot -- eval(*) inside for()

 On Mon, 1 Apr 2019, Martin Maechler wrote: >>>>>> Suharto Anggono Suharto Anggono via R-devel >>>>>>     on Sun, 31 Mar 2019 15:26:13 +0000 writes: > >    > Ah, with R 3.5.0 or R 3.4.2, but not with R 3.3.1, 'eval' >    > inside 'for' makes compiled version behave like >    > non-compiled version. > > Ah.. ... thank you for detecting that  " eval() inside for()" behaves > specially  in how error message get a call or not. Don't count on that remaining true indefinitely. The standard behavior is better and we'll eventually get the case where 'eval' and a few others are called to behave the same. Best, luke > Let's focus only on this issue here. > > I'm adding a 0-th case to make even clearer what you are saying: > >  >  options(error = expression(NULL)) >  >  library(compiler) >  >  enableJIT(0) > >  > f0 <- function(x) { x ; x^2 } ; f0(is.numeric(y)) >  Error in f0(is.numeric(y)) (from #1) : object 'y' not found >  > (function(x) { x ; x^2 })(is.numeric(y)) >  Error in (function(x) { (from #1) : object 'y' not found >  > f0c <- cmpfun(f0) ; f0c(is.numeric(y)) > > so by default, not only the error message but the originating > call is shown as well. > > However, here's your revealing examples: > >  > f <- function(x) for (i in 1) {x; eval(expression(i))} >  > f(is.numeric(y)) >  > # Error: object 'y' not found >  > fc <- cmpfun(f) >  > fc(is.numeric(y)) >  > # Error: object 'y' not found > > I've tried more examples and did not find any difference > between simple interpreted and bytecompiled code {apart > from "keep.source=TRUE" keeping source, sometimes visible}. > So I don't understand yet why you think the byte compiler plays > a role. > > Rather the crucial difference seems  the error happens inside a > loop which contains an explicit eval(.), and that eval() may > even be entirely unrelated to the statement in which the error > happens [above: The error happens when the promise 'x' is > evaluated, *before* eval() is called at all]. > > >    > Is this accidental feature going to be relied upon? > >    [i.e.  *in  stopifnot() R code (which in R-devel and R 3.5.x has >            had an eval() inside the for()-loop)] > > That is a good question. > What I really like about the R-devel case:  We do get errors > signalled that do *not* contain the full stopifnot() call. > > With the newish introduction of the exprs = { ... ... } variant, > it is even more natural to have large exprs in a stopifnot() call, > and when there's one accidental error in there, it's quite > unhelpful to see the full stopifnot(..........) call {many lines > of R code} obfuscating the one statement which produced the > error. > > So it seems I am asking for a new feature in R, > namely to temporarily say: Set the call to errors to NULL "in > the following". > In R 3.5.x, I had used withCallingHandlers(...) to achieve that > and do even similar for warnings... but needed to that for every > expression and hence inside the for loop  and the consequence > was a relatively large slowdown of stopifnot()..  which > triggered all the changes since. > > Whereas what we see here ["eval() inside for()"] is a cheap > automatic suppression of 'call' for the "internal errors", i.e., > those we don't trigger ourselves via stop(simplError(...)). > > ______________________________________________ > [hidden email] mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel> -- Luke Tierney 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:   [hidden email] Iowa City, IA 52242                 WWW:  http://www.stat.uiowa.edu______________________________________________ [hidden email] mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Open this post in threaded view
|

## Re: stopifnot

Open this post in threaded view
|

## Re: [External] Re: stopifnot -- eval(*) inside for()

 In reply to this post by Tierney, Luke >>>>> Tierney, Luke >>>>>     on Mon, 1 Apr 2019 12:41:08 +0000 writes:     > On Mon, 1 Apr 2019, Martin Maechler wrote:     >>>>>>> Suharto Anggono Suharto Anggono via R-devel     >>>>>>> on Sun, 31 Mar 2019 15:26:13 +0000 writes:     >>     >> > Ah, with R 3.5.0 or R 3.4.2, but not with R 3.3.1, 'eval'     >> > inside 'for' makes compiled version behave like     >> > non-compiled version.     >>     >> Ah.. ... thank you for detecting that  " eval() inside for()" behaves     >> specially  in how error message get a call or not.     > Don't count on that remaining true indefinitely. The standard behavior     > is better and we'll eventually get the case where 'eval' and a few     > others are called to behave the same.     > Best,     > luke Yes, Suharto did indeed mention that it may not be a good idea to rely on that behavior, and I did agree ... though my agreement was a bit buried in other stuff. Note that I have been asking if this "accidental" but internally consistent behavior for the current situation, could not be made a feature that the user can ask for ... without having to use a handler (which had been a real slowdown when used inside stopifnot() in R 3.5.3) :   [................]   [................]     >> So it seems I am asking for a new feature in R,     >> namely to temporarily say: Set the call to errors to NULL "in     >> the following".     >> In R 3.5.x, I had used withCallingHandlers(...) to achieve that     >> and do even similar for warnings... but needed to that for every     >> expression and hence inside the for loop  and the consequence     >> was a relatively large slowdown of stopifnot()..  which     >> triggered all the changes since.     >>     >> Whereas what we see here ["eval() inside for()"] is a cheap     >> automatic suppression of 'call' for the "internal errors", i.e.,     >> those we don't trigger ourselves via stop(simpleError(...)). So, for me as programmeR, it would be nice to be able to ask for "this" behavior explicitly in a special case as here, where "no-call" error messages are preferable .. because the call can be really large and is known to be  "almost surely" distracting rather than helpful. Martin ______________________________________________ [hidden email] mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Open this post in threaded view
|

## Re: stopifnot -- eval(*) inside for()

 In reply to this post by Martin Maechler With f <- function(x) for (i in 1) x fc <- cmpfun(f) (my previous example), error message of fc(is.numeric(y)) shows the originating call as well, while error message of f(is.numeric(y)) doesn't. Compiled version behaves differently. Even with f <- function(x) for (i in 1) {x; eval(expression(i))} fc <- cmpfun(f) , error message of fc(is.numeric(y)) shows the originating call in R 3.3.1. As I see, error message only has one line of call. If the deparsed call spans more than one line, the rest is not shown. In 'stopifnot' in R 3.5.x, each is wrapped in 'tryCatch' which is wrapped again in 'withCallingHandlers'. Just one wrapping may be enough. The 'withCallingHandlers' construct in 'stopifnot' in R 3.5.x has no effect anyway, as I said before (https://stat.ethz.ch/pipermail/r-devel/2019-February/077386.html). Also, 'tryCatch' (or 'withCallingHandlers' ...) can wrap the entire 'for' loop. The slowdown can be less than in R 3.5.x. -------------------------------------------- On Mon, 1/4/19, Martin Maechler <[hidden email]> wrote:  Subject: Re: [Rd] stopifnot -- eval(*) inside for()  Cc: [hidden email]  Date: Monday, 1 April, 2019, 5:00 PM   >>>>> Suharto Anggono Suharto Anggono via R-devel >>>>>    on Sun, 31 Mar 2019 15:26:13 +0000 writes:     > Ah, with R 3.5.0 or R 3.4.2, but not with R 3.3.1, 'eval'     > inside 'for' makes compiled version behave like     > non-compiled version. Ah.. ... thank you for detecting that  " eval() inside for()" behaves specially  in how error message get a call or not. Let's focus only on this issue here. I'm adding a 0-th case to make even clearer what you are saying:   >  options(error = expression(NULL))   >  library(compiler)   >  enableJIT(0)   > f0 <- function(x) { x ; x^2 } ; f0(is.numeric(y))   Error in f0(is.numeric(y)) (from #1) : object 'y' not found   > (function(x) { x ; x^2 })(is.numeric(y))   Error in (function(x) { (from #1) : object 'y' not found   > f0c <- cmpfun(f0) ; f0c(is.numeric(y)) so by default, not only the error message but the originating call is shown as well. However, here's your revealing examples:   > f <- function(x) for (i in 1) {x; eval(expression(i))}   > f(is.numeric(y))   > # Error: object 'y' not found   > fc <- cmpfun(f)   > fc(is.numeric(y))   > # Error: object 'y' not found I've tried more examples and did not find any difference between simple interpreted and bytecompiled code {apart from "keep.source=TRUE" keeping source, sometimes visible}. So I don't understand yet why you think the byte compiler plays a role. Rather the crucial difference seems  the error happens inside a loop which contains an explicit eval(.), and that eval() may even be entirely unrelated to the statement in which the error happens [above: The error happens when the promise 'x' is evaluated, *before* eval() is called at all].     > Is this accidental feature going to be relied upon?     [i.e.  *in  stopifnot() R code (which in R-devel and R 3.5.x has             had an eval() inside the for()-loop)] That is a good question. What I really like about the R-devel case:  We do get errors signalled that do *not* contain the full stopifnot() call. With the newish introduction of the exprs = { ... ... } variant, it is even more natural to have large exprs in a stopifnot() call, and when there's one accidental error in there, it's quite unhelpful to see the full stopifnot(..........) call {many lines of R code} obfuscating the one statement which produced the error. So it seems I am asking for a new feature in R, namely to temporarily say: Set the call to errors to NULL "in the following". In R 3.5.x, I had used withCallingHandlers(...) to achieve that and do even similar for warnings... but needed to that for every expression and hence inside the for loop  and the consequence was a relatively large slowdown of stopifnot()..  which triggered all the changes since. Whereas what we see here ["eval() inside for()"] is a cheap automatic suppression of 'call' for the "internal errors", i.e., those we don't trigger ourselves via stop(simplError(...)). ______________________________________________ [hidden email] mailing list https://stat.ethz.ch/mailman/listinfo/r-devel