Why does R say no loop for break/next, jumping to

2020-07-10 03:20发布

Why does R throw the error "Error in value[3L] : no loop for break/next, jumping to top level" instead of going to the next iteration of a loop? I'm on R version 2.13.1 (2011-07-08)

for (i in seq(10)) { 
   tryCatch(stop(), finally=print('whoops'), error=function(e) next) 
}

This problem came up because I wanted to create a different image or no image at all when plot failed. The code, using joran's approach, would look like this:

for (i in c(1,2,Inf)) { 
   fname = paste(sep='', 'f', i, '.png')
   png(fname, width=1024, height=768) 
   rs <- tryCatch(plot(i), error=function(e) NULL)
   if (is.null(rs)){
    print("I'll create a different picture because of the error.")
   }
   else{
    print(paste('image', fname, 'created'))
    dev.off()
    next
   } 
}

标签: r
3条回答
forever°为你锁心
2楼-- · 2020-07-10 03:39

Wouldn't it make more sense to put the next outside the tryCatch based on an if check? Something like this:

for (i in c(1,2,Inf)) { 
   rs <- tryCatch(seq(i), finally=print('whoops'), error=function(e) NULL)
   if (is.null(rs)){
    print("I found an error!")
   }
   else{
    next
   } 
}

although I'm not sure this is what you want, since I'm a little unclear on what you're trying to do.

EDIT

Based on the OP's revisions, this formulation works for me:

plotFn <- function(fname,i){
    png(fname, width=400, height=200)
    plot(i)
    dev.off()
}


for (i in c(1,Inf,3)) { 
   fname = paste('f', i, '.png',sep="")
   rs <- tryCatch(plotFn(fname,i), error=function(e){dev.off(); return(NULL)})
   if (is.null(rs)){
    print("I'll create a different picture because of the error.")
   }
   else{
    print(paste('image', fname, 'created'))
    next
   } 
}

I'm certain that not having a dev.off() call in the case of an error needed to be fixed. I'd have to dig a little deeper to figure out exactly why separating png and plot was causing problems. But I think it's probably cleaner to keep the png(); plot(); dev.off() sequence self contained anyway. Also note that I put a dev.off() in the error function.

I haven't tested what will happen if plotFn throws an error on png(), never creates the device and then reaches the error function and calls dev.off(). Behavior may depend on what else you have going on in your R session.

查看更多
爷的心禁止访问
3楼-- · 2020-07-10 03:48

Maybe you could try :

for (i in seq(10)) { 
   flag <- TRUE
   tryCatch(stop(), finally=print('whoops'), error=function(e) flag<<-FALSE)
   if (!flag) next
}
查看更多
欢心
4楼-- · 2020-07-10 03:53

Unfortunately, once you get inside your error function you're no longer in a loop. There's a way you could hack around this:

for (i in seq(10)) { 
   delayedAssign("do.next", {next})
   tryCatch(stop(), finally=print('whoops'),
        error=function(e) force(do.next))
}

Though that is... well, hacky. Perhaps there is a less hacky way, but I don't see one right off.

(This works because delayedAssign happens every loop, canceling out the efforts of force)

EDIT

Or you could use continuations:

for (i in seq(10)) { 
   callCC(function(do.next) {
       tryCatch(stop(), finally=print('whoops'),
           error=function(e)    do.next(NULL))
       # Rest of loop goes here
       print("Rest of loop")
   })
}

EDIT

As Joris points out, you probably shouldn't actually use either of these, because they're confusing to read. But if you really want to call next in a loop, this is how :).

查看更多
登录 后发表回答