我知道on.exitR 中的功能,这很棒.它在调用函数退出时运行表达式,正常或作为错误的结果.
我想要的是表达式仅在调用函数正常返回时运行,而不是在出错的情况下运行.我有多个函数可以正常返回的点,以及可能失败的多个点.有没有办法做到这一点?
myfunction = function() {
...
on.exit( if (just exited normally without error) <something> )
...
if (...) then return( point 1 )
...
if (...) then return( point 2 )
...
if (...) then return( point 3 )
...
return ( point 4 )
}
Run Code Online (Sandbox Code Playgroud)
Jor*_*eys 13
整点on.exit()是完全不管的退出状态下运行.因此它忽略了任何错误信号.这finally与tryCatch函数的语句相当.
如果您只想在正常退出时运行代码,只需将其放在代码的末尾即可.是的,您将不得不使用else语句重新构建它,并且只创建一个退出点,但这被一些人认为是良好的编码实践.
使用您的示例,那将是:
myfunction = function() {
...
if (...) then out <- point 1
...
else if (...) then out <- point 2
...
else if (...) then out <- point 3
...
else out <- point 4
WhateverNeedsToRunBeforeReturning
return(out)
}
Run Code Online (Sandbox Code Playgroud)
或者查看Charles的答案,以便使用这个想法很好地实现local().
如果你坚持使用on.exit(),你可以赌博回溯机制的工作来做这样的事情:
test <- function(x){
x + 12
}
myFun <- function(y){
on.exit({
err <- if( exists(".Traceback")){
nt <- length(.Traceback)
.Traceback[[nt]] == sys.calls()[[1]]
} else {FALSE}
if(!err) print("test")
})
test(y)
}
Run Code Online (Sandbox Code Playgroud)
.Traceback包含导致错误的最后一个调用堆栈.您必须检查该堆栈中的最高呼叫是否等于当前呼叫,在这种情况下,您的呼叫很可能会抛出最后一个错误.因此,基于这种情况,您可以尝试破解自己从未使用过的解决方案.
只需使用您想要完成的代码包装所有返回函数调用的args.所以你的例子变成了:
foo = function(thing){do something; return(thing)}
myfunction = function() {
...
if (...) then return( foo(point 1) )
...
if (...) then return( foo(point 2) )
...
if (...) then return( foo(point 3) )
...
return ( foo(point 4) )
}
Run Code Online (Sandbox Code Playgroud)
或者只是将每个then子句分成两个语句.使用on.exit一些代码进入许多地方会引起一些远距离的怪异行为问题并使婴儿Dijkstra哭泣(阅读Dijkstra的"GOTO认为有害"论文).
关于@Joris答案的评论更具可读性:
f = function() {
ret = local({
myvar = 42
if (runif(1) < 0.5)
return(2)
stop('oh noes')
}, environment())
# code to run on success...
print(sprintf('myvar is %d', myvar))
ret
}
Run Code Online (Sandbox Code Playgroud)