while TRUE + 在子环境中中断
Posted
技术标签:
【中文标题】while TRUE + 在子环境中中断【英文标题】:while TRUE + break in a sub-environment 【发布时间】:2016-07-11 00:04:09 【问题描述】:我无法让while(TRUE)
循环工作。我认为这个例子解决了问题的症结:
l <- list(x = 5)
while (TRUE)
with(l, if (x > 100) break else l$x <<- x + 5)
运行出错:
eval(expr, envir, enclos)
中的错误:break/next 没有循环,跳转到顶层
奇怪的是,while
循环似乎已成功执行:
l
# $x
# [1] 105
看来问题是我在子环境中发送break
语句,因为以下内容按预期工作而没有错误:
x = 5
while(TRUE)
if (x > 100) break else x <<- x+5
认为这只是环境问题,我也尝试将break
替换为eval(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
【问题讨论】:
有理由使用with
吗?为什么不只是if (l$x>100) break else l$x<-l$x+100
?
@nicola 问题的上下文略有不同;我选择这个来复制我认为是必需品的东西。也就是说,在我的实际使用中,break
是在对[.data.table
的调用中发送的
也许更好地解释上下文会有所帮助,因为这里很明显是环境问题:while(TRUE) with(l,break)
产生相同的错误。显然,with
产生了一个环境,R 不希望从中产生break
。
R 的with
只是一个函数。所以你实际上是在这样做:while(TRUE) (function() break)()
。 break
在内部函数范围内,而while
在外部函数范围内。
@AWebb 谢谢,我知道with
-equals-function 位,麻烦在于找出确切评估break
的位置,因为while
正在自己工作环境
【参考方案1】:
@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)
这避免了解析文本字符串,因此看起来不那么老套。在捕获的环境env
中进行评估允许循环在 R 代码中的任何级别,而不仅仅是在 .GlobalEnv 中。这就像一个非本地跳转(又名 GOTO),这使得推理代码变得更加困难。
【讨论】:
还有evalq(break, parent.env(environment()))
。如果break
被发送到错误的环境,我仍然不确定为什么原始代码不是无限循环。有什么原因吗?
@MichaelChirico 最好明确 env= 而不是依赖调用堆栈的顺序进行发现,因为程序员可能会无意中更改调用堆栈。原始代码产生了一个错误,并且由于该错误,循环结束了。
哦,这很有道理。【参考方案2】:
也许我不明白这个问题的所有利害关系,但你可以试试:
l <- list(x = 5)
while (TRUE)
with(l, if (x > 100) eval(parse(text="break"), envir=.GlobalEnv) else l$x <<- x + 5)
【讨论】:
抱歉,刚回来。我认为@Martin Morgan 解释了这种方法,甚至改进了它。赞一个!以上是关于while TRUE + 在子环境中中断的主要内容,如果未能解决你的问题,请参考以下文章