环境和惰性求值:摆脱符号和获取值

问题描述

我正试图解决我遇到的一个问题,我认为它主要围绕环境、惰性评估和与这些事情相关的问题。我有一个主要功能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,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,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,d=d)
  }
  return(foo)
}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...