【问题标题】:Why does R say no loop for break/next, jumping to top level为什么R说没有循环中断/下一个,跳到顶层
【发布时间】:2011-08-11 22:45:06
【问题描述】:

为什么 R 会抛出错误“值错误 [3L] : no loop for break/next, jumping to top level”而不是进入循环的下一次迭代?我在 R 版本 2.13.1 (2011-07-08)

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

出现这个问题是因为我想在绘图失败时创建不同的图像或根本没有图像。使用 joran 方法的代码如下所示:

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 说没有循环用于 break/next,跳转到顶层”,这个答案在这里做得很好:@ 987654321@
  • 我觉得eval(expr = next, envir = parent.frame(n = 1)) 或类似的解决方案应该可以工作,但我无法让它工作。也许其他人会知道。

标签: r


【解决方案1】:

也许你可以试试:

for (i in seq(10)) { 
   flag <- TRUE
   tryCatch(stop(), finally=print('whoops'), error=function(e) flag<<-FALSE)
   if (!flag) next
}

【讨论】:

    【解决方案2】:

    不幸的是,一旦您进入 error 函数,您就不再处于循环中。有一种方法可以解决这个问题:

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

    虽然那是……嗯,很老套。也许有一种不那么老套的方法,但我看不到。

    (这是因为delayedAssign 在每个循环中都会发生,抵消了force 的努力)

    编辑

    或者你可以使用延续:

    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")
       })
    }
    

    编辑

    正如 Joris 指出的那样,您可能实际上不应该使用其中任何一个,因为它们读起来令人困惑。但是如果你真的想在循环中调用next,这就是方法:)。

    【讨论】:

    • 是的,它们似乎都对我有用。虽然我没有这么说,但如果 plot 命令失败,这段代码应该不会创建 png。也许我设置错了。情节会去哪里停止。
    • +1 很好的解释,尽管我强烈建议不要使用您的构造。有更好的编程流程可以产生相同的结果,而无需四处乱窜。把你想做的事情放在一个内部函数中,然后把它包装在 tryCatch 中。
    • @Joris 是的,你说得对。我只是对从函数中调用next 的想法很感兴趣。我会添加一个注释为我的精神错乱道歉;)
    【解决方案3】:

    基于if 检查将next 放在tryCatch 之外不是更有意义吗?像这样的:

    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
       } 
    }
    

    虽然我不确定这是你想要的,因为我有点不清楚你想要做什么。

    编辑

    根据 OP 的修订,这个公式对我有用:

    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
       } 
    }
    

    我确定在需要修复错误的情况下没有dev.off() 调用。我必须更深入地了解为什么将pngplot 分开会导致问题。但我认为无论如何保持png(); plot(); dev.off() 序列自包含可能更清洁。另请注意,我在错误函数中添加了dev.off()

    我还没有测试过如果plotFnpng() 上抛出一个错误,永远不会创建设备然后到达错误函数并调用dev.off() 会发生什么。行为可能取决于您在 R 会话中进行的其他操作。

    【讨论】:

    • 我编辑了问题以使用您的代码来做我想做的事情。请注意,它并不完全有效,因为 plot 每次都会抛出错误。
    猜你喜欢
    • 1970-01-01
    • 2021-10-20
    • 1970-01-01
    • 2012-06-02
    • 2021-03-30
    • 2019-07-03
    • 1970-01-01
    • 1970-01-01
    • 2015-11-11
    相关资源
    最近更新 更多