环境和懒惰评估:摆脱符号并获得价值

Environments and lazy evaluation: getting rid of symbols and getting values

我正在努力解决我 运行 遇到的一个问题,我认为这个问题主要围绕环境、惰性评估和与这些事情相关的问题展开。我有一个主要功能(下面的 foo1),在我的实际用例中它非常广泛。出于这个原因,我试图提供一些包装函数(foo2foo3)来修改主函数的特定元素。

我的问题是,我最终没有获得实际值,而是获得了符号。有人可以提供一些指导,说明我需要对环境进行哪些处理以及哪些不可以进行排序吗?

这是我的 MWE:

foo1 <- function(foo, a, b, c=1, d=1) {
  if (!missing(foo)) {
    mcall <- as.list(match.call())[-(1:2)]
    call_names <- names(mcall)
    foo <- foo[-which(names(foo) %in% call_names)]
    foo <- c(foo, mcall)
  } else {
    foo <- list(a=a, b=b, c=c, d=d)
  }
  return(foo)
}

foo2 <- function(a, b) {
  foo1(a=a, b=b)
}

foo3 <- function(foo, c, d) {
  foo1(foo, c=c, d=d)
}

f <- foo2(a=1, b=1) 
f <- foo3(f, c=2, d=2)
str(f)

> str(f)
List of 4
 $ a: num 1
 $ b: num 1
 $ c: symbol c
 $ d: symbol d

这里我希望cd等于2,但它们是符号。

当您使用 match.call 时,它会阻止对参数进行评估。如果你想评估参数,那么你需要明确地这样做。例如

foo1 <- function(foo, a, b, c=1, d=1) {
  if (!missing(foo)) {
    mcall <- as.list(match.call())[-2]
    mcall[[1]] <- quote(list)
    mcall <- eval(as.call(mcall))
    call_names <- names(mcall)
    foo <- foo[-which(names(foo) %in% call_names)]
    foo <- c(foo, mcall)
  } else {
    foo <- list(a=a, b=b, c=c, d=d)
  }
  return(foo)
}

这会将对 foo1 的调用转换为对 list() 的调用并计算结果。另一种选择是将 mget() 与您要捕获的本地环境中的变量一起使用。这将触发评估

foo1 <- function(foo, a, b, c=1, d=1) {
  if (!missing(foo)) {
    mlist <- mget(intersect(setdiff(ls(), "foo"), names(match.call())))
    call_names <- names(mlist)
    foo <- foo[-which(names(foo) %in% call_names)]
    foo <- c(foo, mlist)
  } else {
    foo <- list(a=a, b=b, c=c, d=d)
  }
  return(foo)
}