在父上下文中调用浏览器

时间:2018-10-15 14:02:56

标签: r

假设我有以下代码:

maybeBrowser <- function (msg) {
    if (interactive()) {
        cat(msg, "\n")
        ???
    } else {
        stop(msg)
    }
}

foo <- function (cond, ...) {
    if (cond) maybeBrowser("What a mess")
}

会是什么???如果browser()的计算结果为TRUE,则必须在foo的上下文中调用cond

1 个答案:

答案 0 :(得分:2)

也许不是最优雅,但这似乎可以满足我的要求。

首先,有两个注意事项:

  1. 我要添加browser(); 1,因为它无法立即生效。 ;1是因为browser()如果后面没有任何代码,将立即退出。如果if/else块后面有东西,那么您可能不需要它,但是它已经存在。 (只有emacs / ESS:https://github.com/emacs-ess/ESS/issues/178才需要)

  2. 我在foo环境中添加了一个变量,以证明我们看不到(然后看到)。

首先,失败的尝试:

maybeBrowser <- function (msg) {
    if (interactive()) {
        cat(msg, "\n")
        browser()
        q
    } else {
        stop(msg)
    }
}
foo <- function (cond, ...) {
    cat(capture.output(environment()), "\n")
    in_foo <- 1
    if (cond) maybeBrowser("What a mess")
}

foo(TRUE)
# <environment: 0x000000001b2beba0> 
# What a mess 
# Called from: maybeBrowser("What a mess")
# Browse[1]> 
debug at #5: q
# Browse[2]> 
environment()
# <environment: 0x000000001b280030>  <---- this is different
# Browse[2]> 
ls()
# [1] "msg"

现在根据https://stackoverflow.com/a/23891089/3358272

修改代码
maybeBrowser <- function (msg) {
    if (interactive()) {
        cat(msg, "\n")
        return(evalq(browser(skipCalls=1), envir=parent.frame()))
    } else {
        stop(msg)
    }
}
foo <- function (cond, ...) {
    cat(capture.output(environment()), "\n")
    in_foo <- 1
    if (cond) maybeBrowser("What a mess")
}

foo(TRUE)
# <environment: 0x000000001b0b9d40> 
# What a mess 
# Called from: eval(quote({
#     browser()
#     1
#   ...
# Browse[1]> 
debug at #4: [1] 1
# Browse[3]> 
environment()
# <environment: 0x000000001b0b9d40>  <---- this is now the same
# Browse[3]> 
ls()
# [1] "cond"   "in_foo"

但是,这不允许您继续执行foo中的以下任何代码,因此答案是不完整的。不幸的是,我认为这可能不可行……但也许更内部分析的R bubba对此会更加清楚。