首页 > 解决方案 > 是否可以在 R 中进行动态绑定?

问题描述

是否可以在 R 中使用具有动态绑定的变量?说,有这样的工作:

f1a <- function() {
  x <- 1
  f2()
}

f1b <- function() {
  x <- 2
  f2()
}

f2 <- function() {
  f3()
}

f3 <- function() {
  # print x
}

f1a() # prints 1
f1b() # prints 2

我可以x明确地传递堆栈,但这不是我想要的。我在询问动态绑定的可能性。我知道很多人会说x明确传递总是可取的,但假设我不能更改f2(I can change f1a, f1band f3) 的定义。当然,我可以有一个全局变量,但如果可能的话,我宁愿使用动态绑定。

标签: r

解决方案


f1a <- function() {
  x <- 1
  f2()
}

f1b <- function() {
  x <- 2
  f2()
}

f2 <- function() {
  f3()
}

f3 <- function() {
  get("x", envir = parent.frame(2))
}

只需移动f3正在寻找变量的环境x

> f1a()
[1] 1
> f1b()
[1] 2

get("x", envir = parent.frame(2))x在调用堆栈两帧的环境中查找带符号的变量:

f3 <- function() {
  get("x", envir = parent.frame(2))
  rlang::trace_back()
}

> f1a()
    █
 1. └─global::f1a()
 2.   └─global::f2()
 3.     └─global::f3()

如果您需要遍历整个调用堆栈直到遇到第一个符号,只需使用dynGet()

f1a <- function() {
  x <- 1
  f2()
}

f1b <- function() {
  x <- 2
  f2()
}

f2 <- function() {
  f3()
}

f3 <- function() {
  f4()
}

f4 <- function() {
  f5()
}

f5 <- function() {
  dynGet("x")
}

> f1a()
[1] 1
> f1b()
[1] 2

这将在第一次x遇到从调用环境向上移动调用堆栈时停止。所以如果我们调整f2

f2 <- function() {
  x <- 3
  f3()
}

> f1a()
[1] 3
> f1b()
[1] 3

同样,完整的调用堆栈可以通过以下方式看到rlang::trace_back

f5 <- function() {
  dynGet("x")
  rlang::trace_back()
}

> f1a()
    █
 1. └─global::f1a()
 2.   └─global::f2()
 3.     └─global::f3()
 4.       └─global::f4()
 5.         └─global::f5()

推荐阅读