首页 > 解决方案 > 动态地将控制移动到调用堆栈中的其他位置

问题描述

这个用例中,我想动态地将控制移动到调用堆栈中的其他位置。这可能吗?下面,如果我们修改并不理会身体,我们可以top_level()返回 2吗?return_2_from_top_level()top_level()

# Do not modify this:
top_level <- function() {
  return_2_from_top_level()
  Sys.sleep(2)
  1
}

# Modify this:
return_2_from_top_level <- function() {
  # What can we do here to make top_level() return 2?
  evalq(return(2), sys.frame(1)) # Does not work, but kind of shows the idea.
}

# We want 2, not 1:
top_level()
#> [1] 1

reprex 包于 2020-01-11 创建(v0.3.0)

期望的结果:

top_level()
#> [1] 2

# We still want this function body for top_level():
body(top_level)
#> {
#>     return_2_from_top_level()
#>     Sys.sleep(2)
#>     1
#> }

标签: r

解决方案


可能您可以首先修改整个设置以避免这种情况,但如果没有,则callCC可以使用。

1)重要的是return_2_from_top_level必须知道,g因此我们将指示的功能环境重置为已知的top环境。g

return_2_from_top_level <- function() g(2)

top_level <- function() { 
  return_2_from_top_level()
  Sys.sleep(2)
  1
}

top <- function(g) {
  environment(return_2_from_top_level) <- environment()
  environment(top_level) <- environment()
  top_level()   
}

callCC(top)
## [1] 2

2)或者,我们可以将 和 的定义top_level移入 return_2__from_top_leveltop在这种情况下,没有明确的环境混乱。

top <- function(g) {

  return_2_from_top_level <- function() g(2)

  top_level <- function() { 
    return_2_from_top_level()
    Sys.sleep(2)
    1
  }

  top_level()   

}

callCC(top)
## [1] 2

3)另一种可能性是复制g到全局环境中。

return_2_from_top_level <- function() g(2)

top_level <- function() { 
  return_2_from_top_level()
  Sys.sleep(2)
  1
}

top <- function(g) {
  g <<- g
  top_level()   
}

callCC(top)
## [1] 2

推荐阅读