gpt4 book ai didi

r - 使用 `withCallingHandlers`捕获任意条件

转载 作者:行者123 更新时间:2023-12-04 04:05:37 25 4
gpt4 key购买 nike

问题

我正在尝试编写一个函数,该函数将评估代码并存储结果,包括代码中表示的任何可能的条件。除了在错误处理表达式中运行我的函数(我们称其为evalcapt)的情况之外,我的工作非常正常。

问题是withCallingHandlers将继续寻找匹配的条件处理程序,如果有人在我的函数之外定义了这样的处理程序,则我的函数将失去执行控制权。这是问题的简化示例:

evalcapt <- function(expr) {
conds <- list()
withCallingHandlers(
val <- eval(expr),
condition=function(e) {
message("Caught condition of class ", deparse(class(e)))
conds <<- c(conds, list(e))
} )
list(val=val, conditions=conds)
}

myCondition <- simpleCondition("this is a custom condition")
class(myCondition) <- c("custom", class(myCondition))
expr <- expression(signalCondition(myCondition), 25)

tryCatch(evalcapt(expr))

按预期工作
Caught condition of class c("custom", "simpleCondition", "condition")
$val
[1] 25

$conditions
$conditions[[1]]
<custom: this is a custom condition>

但:
tryCatch(
evalcapt(expr),
custom=function(e) stop("Hijacked `evalcapt`!")
)

不起作用:
Caught condition of class c("custom", "simpleCondition", "condition")
Error in value[[3L]](cond) : Hijacked `evalcapt`!

我不知道如何实现的解决方案

我真正需要的是一种在代码中发出条件后立即定义重新启动的方法,坦率地说, withCallingHandlers看起来正常工作(当我的处理程序是最后一个可用的处理程序时),但是我看不到重新启动已建立当我在处理函数中使用 browse并使用 computeRestarts时。

似乎无法解决的问题

使用 tryCatch tryCatchwithCallingHandlers没有相同的问题,因为它在找到第一个后不再继续寻找处理程序。最大的问题是条件后它也不会继续评估代码。如果您看上面的示例,但是 tryCatch中的子元素为 withCallingHandlers,则不会返回值(25),因为在处理了条件之后,执行又回到了 tryCatch框架中。

因此,基本上,我正在寻找tryCatchwithCallingHandlers之间的混合体,该混合体将控制权返回给条件信号器,但在找到第一个处理程序后也停止寻找更多处理程序。

将表达式分解为子表达式,然后使用 tryCatch
好的,但是您如何分解(以及到处都是带有信号状态的更复杂的功能):
fun <- function(myCondition) {
signalCondition(myCondition)
25
}
expr <- expression(fun())

杂项

我寻找了与 .Internal(.signalCondition())调用相关的源代码,以查看是否可以确定是否设置了幕后重新启动,但是我不了解那里的内容。这好像是:
    void R_ReturnOrRestart(SEXP val, SEXP env, Rboolean restart)
{
int mask;
RCNTXT *c;

mask = CTXT_BROWSER | CTXT_FUNCTION;

for (c = R_GlobalContext; c; c = c->nextcontext) {
if (c->callflag & mask && c->cloenv == env)
findcontext(mask, env, val);
else if (restart && IS_RESTART_BIT_SET(c->callflag))
findcontext(CTXT_RESTART, c->cloenv, R_RestartToken);
else if (c->callflag == CTXT_TOPLEVEL)
error(_("No function to return from, jumping to top level"));
}
}

来自src/main/errors.c的命令正在执行一些重新启动调用,这由 do_signalCondition调用,但是我不知道如何处理此问题。

最佳答案

我认为您正在寻找的是在发出特殊情况时使用withRestarts,例如从warning:

    withRestarts({
.Internal(.signalCondition(cond, message, call))
.Internal(.dfltWarn(message, call))
}, muffleWarning = function() NULL)

所以
evalcapt <- function(expr) {
conds <- list()
withCallingHandlers(
val <- eval(expr),
custom=function(e) {
message("Caught condition of class ", deparse(class(e)))
conds <<- c(conds, list(e))
invokeRestart("muffleCustom")
} )
list(val=val, conditions=conds)
}

expr <- expression(withRestarts({
signalCondition(myCondition)
}, muffleCustom=function() NULL), 25)

导致
> tryCatch(evalcapt(expr))   
Caught condition of class c("custom", "simpleCondition", "condition")
$val
[1] 25

$conditions
$conditions[[1]]
<custom: this is a custom condition>


> tryCatch(
+ evalcapt(expr),
+ custom=function(e) stop("Hijacked `evalcapt`!")
+ )
Caught condition of class c("custom", "simpleCondition", "condition")
$val
[1] 25

$conditions
$conditions[[1]]
<custom: this is a custom condition>

关于r - 使用 `withCallingHandlers`捕获任意条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20572288/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com