环境和懒惰评估:摆脱符号并获得价值
Environments and lazy evaluation: getting rid of symbols and getting values
我正在努力解决我 运行 遇到的一个问题,我认为这个问题主要围绕环境、惰性评估和与这些事情相关的问题展开。我有一个主要功能(下面的 foo1
),在我的实际用例中它非常广泛。出于这个原因,我试图提供一些包装函数(foo2
和 foo3
)来修改主函数的特定元素。
我的问题是,我最终没有获得实际值,而是获得了符号。有人可以提供一些指导,说明我需要对环境进行哪些处理以及哪些不可以进行排序吗?
这是我的 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
这里我希望c
和d
等于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)
}
我正在努力解决我 运行 遇到的一个问题,我认为这个问题主要围绕环境、惰性评估和与这些事情相关的问题展开。我有一个主要功能(下面的 foo1
),在我的实际用例中它非常广泛。出于这个原因,我试图提供一些包装函数(foo2
和 foo3
)来修改主函数的特定元素。
我的问题是,我最终没有获得实际值,而是获得了符号。有人可以提供一些指导,说明我需要对环境进行哪些处理以及哪些不可以进行排序吗?
这是我的 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
这里我希望c
和d
等于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)
}