gpt4 book ai didi

r - 自定义环境中的范围(功能)

转载 作者:行者123 更新时间:2023-12-05 00:00:34 28 4
gpt4 key购买 nike

我有一个特殊的(虚拟)函数,我想在沙盒环境中使用它:

disable.system.call <- function(...) {
mc <- match.call()
if (grepl('system', deparse(mc[[2]])))
stop('NONO')
eval(mc, env = .GlobalEnv)
}

它没有什么特别的,只是检查第一个参数是否有 system名字中的单词。这只是一个 POC 示例。

我稍后要做的:我将这个简单的函数分配给一些 basestats查看计算表达式是否包含 system 的函数word 作为第一个参数。例如。:
e <- new.env()
eval(parse(text = 'model.frame <- disable.system.call'), envir = e)

这很酷,因为没有 system 的调用inside 就像一个魅力,但过滤器工作:
> eval(parse(text = 'model.frame("1 ~ 1")'), envir = e)
1
1 1
> eval(parse(text = 'model.frame(\'1 ~ system("ls -la")\')'), envir = e)
Error in model.frame("1 ~ system(\"ls -la\")") : NONO

它甚至可以使用 lm调用 model.frame在里面找到了一个类似字符串的公式:
> eval(parse(text = 'lm(\'1 ~ system("ls -la")\')'), envir = e)
Error in model.frame(formula = "1 ~ system(\"ls -la\")", drop.unused.levels = TRUE) :
NONO

我尝试更进一步,并将那个非常简单的函数( disable.system.call )分配给 as.formulamodel.frame 调用.不幸的是,我还没有做到这一点:
> e <- new.env()
> eval(parse(text = 'as.formula <- disable.system.call'), envir = e)
> eval(parse(text = 'as.formula("1 ~ 1")'), envir = e)
1 ~ 1
> eval(parse(text = 'as.formula(\'1 ~ system("ls -la")\')'), envir = e)
Error in as.formula("1 ~ system(\"ls -la\")") : NONO
> eval(parse(text = 'model.frame(\'1 ~ system("ls -la")\')'), envir = e)
1 system("ls -la")
1 1 0
> eval(parse(text = 'lm(\'1 ~ system("ls -la")\')'), envir = e)

Call:
lm(formula = "1 ~ system(\"ls -la\")")

Coefficients:
(Intercept) system("ls -la")
1 NA

据我所知 model.frame正在调用 as.formula但这不起作用(从上面的输出可以看出)。我很确定这不是因为 model.frame正在调用 stats::as.formulalm上面调用 model.frame在自定义环境中。

任何提示和想法都会受到欢迎!

最佳答案

虽然你怀疑不是这样,stats:::model.frame.default正在调用,而不是环境中的自定义版本 e . (这当然是您通常期望从打包函数中获得的行为。在您的第一个示例中看到的奇怪范围是一种特殊情况,因为 lm() 使用了“非标准评估”,这在我的答案的底部)。

如下所示,您可以使用 trace()查看 as.formula() 的哪个版本在您的每种情况下都会被调用:

disable.system.call <- function(...) {
mc <- match.call()
if (grepl('system', deparse(mc[[2]])))
stop('NONO')
eval(mc, env = .GlobalEnv)
}
e <- new.env()
eval(parse(text = 'as.formula <- disable.system.call'), envir = e)


# (1) trace custom 'as.formula()' in environment e
trace(e$as.formula)


# Calling model.frame() **does not** call the the custom as.formula()
eval(parse(text = 'model.frame(\'1 ~ system("ls -la")\')'), envir = e)
# 1 system("ls -la")
# 1 1 127

# (2) trace stats:::as.formula()
trace(stats:::as.formula)

# Calling model.frame() **does** call stats:::as.formula()
eval(parse(text = 'model.frame(\'1 ~ system("ls -la")\')'), envir = e)
# trace: as.formula
# 1 system("ls -la")
# 1 1 127

编辑 : FWIW,你自定义的原因 model.frame() lm() 调用在第一个示例中是 lm()采用有时称为“非标准评估”的方法。 ( See this pdf 比您可能想要的更多。)关键是 lm()实际指挥 model.frame()在调用环境中进行评估;在您的情况下,这导致它找到了您的功能版本。

原因 lm()使用非标准评价是这样 model.frame()可以访问公式中命名的变量,即使它们是在调用环境中找到的(而不仅仅是能够访问通过 data 参数传入 lm() 的变量)。正如 Thomas Lumley 在链接的 pdf 中所说:

If variables in the formula were required to be in the data argument life would be a lot simpler, but this requirement was not made when formulas were introduced.



如果您有兴趣,这里是 lm 定义中的相关行:
mf <- match.call(expand.dots = FALSE)
...
mf[[1L]] <- as.name("model.frame")
mf <- eval(mf, parent.frame())

关于r - 自定义环境中的范围(功能),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10066311/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com