而TRUE +在子环境中中断

Mic*_*ico 6 r break while-loop

我无法让while(TRUE)循环工作.我认为这个例子解决了问题的关键:

l <- list(x = 5)

while (TRUE){
  with(l, if (x > 100) break else l$x <<- x + 5)
}
Run Code Online (Sandbox Code Playgroud)

哪个运行有错误:

错误eval(expr, envir, enclos):

没有循环中断/下一步,跳到顶级

奇怪的是,while循环似乎已成功执行:

l
# $x
# [1] 105
Run Code Online (Sandbox Code Playgroud)

看来问题是我break在子环境中发送语句,因为以下按预期工作而没有错误:

x = 5

while(TRUE){
  if (x > 100) break else x <<- x+5
}
Run Code Online (Sandbox Code Playgroud)

我以为这只是一个环境问题,我也试过更换breakeval(break, parent.env())eval(break, parent.frame()),但无济于事.

我怎么能阻止这个错误?


我想sessionInfo()可能是相关的:

R version 3.2.4 (2016-03-10)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 14.04.3 LTS

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C               LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
 [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8    LC_PAPER=en_US.UTF-8       LC_NAME=C                 
 [9] LC_ADDRESS=C               LC_TELEPHONE=C             LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] readxl_0.1.0.9000 data.table_1.9.6  haven_0.2.0      

loaded via a namespace (and not attached):
[1] rsconnect_0.4.1.11 tools_3.2.4        Rcpp_0.12.1        chron_2.3-47      
Run Code Online (Sandbox Code Playgroud)

Mar*_*gan 3

@Vongo 建议的一个变体是捕获应该使用 进行评估的环境environment(),然后使用evalq()break评估放在正确的位置。

l <- list(x = 5)
while (TRUE){
    env <- environment()
    with(l, if (x > 100) evalq(break, env) else l$x <<- x + 5)
}
Run Code Online (Sandbox Code Playgroud)

这避免了解析文本字符串,因此看起来不那么麻烦。在捕获的环境中进行评估env允许循环位于 R 代码中的任何级别,而不仅仅是在 .GlobalEnv 中。这就像非本地跳转(又名 GOTO),这使得推理代码变得更加困难。