在browser
的帮助文件中,有两个看似非常相似的选项:
f
完成当前循环或函数的执行
c
退出浏览器并在下一个语句处继续执行。
他们之间有什么区别,在什么情况下差别很明显?
关于可能有什么区别的一些线索 - 我写了一个名为browse.R
的脚本,其中包含以下内容:
for (i in 1:2){
browser()
print(i)
}
这是使用c
与f
的结果:
> source("browse.R")
Called from: eval(expr, envir, enclos)
Browse[1]> c
[1] 1
Called from: eval(expr, envir, enclos)
Browse[1]> c
[1] 2
> source("browse.R")
Called from: eval(expr, envir, enclos)
Browse[1]> f
[1] 1
Browse[2]> f
[1] 2
请注意,Browse[n]
的级别会发生变化。这仍然没有强调它们之间的任何实际差异。
我还试图看看是否可能会从浏览器环境中消失:
for (i in 1:2){
a <- "not modified"
browser()
print(a)
}
Called from: top level
Browse[1]> a <- "modified"
Browse[1]> f
[1] "modified"
Browse[1]> a
[1] "not modified"
Browse[1]> a <- "modified"
Browse[1]> c
[1] "modified"
所以那里也没有区别。
答案 0 :(得分:9)
存在细微差别。
c
立即退出浏览器(和调试模式),之后以正常方式执行其余代码。f
在执行函数/循环的其余部分时保留在浏览器(和调试模式)中。函数/循环完成后,他也返回到正常执行模式。来源:R-source(第1105-1117行)和R-help
这有一些含义:
c
关闭浏览器。这意味着从函数调用新的浏览器调用。因此,您会看到以下行:Called from: function()
。另一方面,f
不会关闭浏览器,因此您不会看到此行。此行为的源代码位于:https://github.com/wch/r-source/...。f
保留在浏览器中,f
也会跟踪上下文级别:浏览器提示的格式为Browse [n]&gt;:此处var {n}表示“浏览器级别”。浏览时可以调用浏览器(通常是在使用调试时),每次递归调用都会增加数量。 (实际数字是上下文堆栈中'contexts'的数量:对于外部浏览级别通常为2,在调试器中检查转储时为1)
可以使用以下代码测试这些差异:
> test <- function(){
browser()
browser()
}
> test()
Called from: test()
Browse[1]> c
Called from: test()
Browse[1]> c
> test()
Called from: test()
Browse[1]> f
Browse[2]> f
据我所知,除非在上下文堆栈中存在实际目的,否则两者之间没有实际区别。调试模式没有附加值。调试标志仅在您输入函数时打开浏览器,但由于您已经在函数内部,因此不会触发其他效果。
答案 1 :(得分:3)
至少对我而言,我觉得答案可以作为一个表格绘制出来,但是,让我们首先考虑浏览器()的用法,以便那些可能还没有遇到过它的人。
browser
函数是大多数R调试技术的基础。本质上,对browser
的调用会停止执行并启动一个特殊的交互式会话,您可以在其中检查计算的当前状态并一次单步执行一个代码命令。
进入浏览器后,您可以执行任何R命令。例如,可以使用ls()查看本地环境;或者选择设置新变量,或者仅使用标准方法为变量赋值来更改分配给变量的值。浏览器也了解一小部分 命令具体到它。这引导我们讨论完成和继续 ...
与完成和继续相关的微妙之处在于:
至少对我来说,你必须在调试用R编写的程序的上下文中查看。具体来说,你可以如何应用完成和继续。我相信很多人都明白这一点,但我包括了完整性,因为我个人确实没有这么长时间。
browser
允许您查看放置浏览器调用的函数中的对象。recover
允许您查看这些对象以及该函数调用者和所有其他活动函数中的对象。
在您编写函数时,自由使用browser
,recover
,cat
和print
可以让您的期望和R的期望收敛。
这样做的一个非常方便的方法是跟踪。例如,如果浏览 myFun函数的结尾很方便,那么你可以这样做:
trace(myFun, exit=quote(browser()))
您可以使用以下命令自定义跟踪:
trace(myFun, edit=TRUE)
如果遇到错误,则调试是适当的操作。有。在 至少有两种调试方法。第一种方法是看状态 在发生错误的位置播放。通过设置错误做好准备 选项。最可能的两个选择是:
options(error=recover)
或
options(error=dump.frames)
不同之处在于,recover
会自动投入调试
模式,但使用dump.frames
,您可以通过执行以下命令开始调试:
debugger()
在任何一种情况下,您都会看到一系列框架(环境) 有效的功能检查。
您可以强制R使用以下命令将警告视为错误:
options(warn=2)
如果要在.First
功能中设置错误选项,则需要a
诀窍,因为在.First
执行时并非一切都到位:
options(error=expression(recover()))
或
options(error=expression(dump.frames()))
调试的第二个想法是在执行时逐步执行函数。如果 你想通过功能myfun,然后执行:
debug(myfun)
然后执行涉及myfun的声明。调试完成后, 做:
undebug(myfun)
这种调试的更复杂版本可以在 调试包。
参考文献:
答案 2 :(得分:0)
您可以将finish
视为其他语言中的break
。发生的事情是,您不再关心迭代中的其他项目,因为某些条件(例如查找特定项目或可能导致错误的项目)。
continue
将停止在循环的当前行,忽略代码块的其余部分,并继续迭代中的下一个项目。如果您打算遍历迭代中的每个项目并忽略满足条件的项目,则可以使用此选项。