首页 > 解决方案 > 如何避免评估和解析?

问题描述

我编写了一个函数,该函数可以获取包含其他函数脚本的文件,并将这些函数存储在另一个环境中,这样它们就不会弄乱全局环境。该代码有效,但包含以下三个实例eval(parse(...))

# sourceFunctionHidden ---------------------------
# source a function and hide the function from the global environment
sourceFunctionHidden <- function(functions, environment = "env", ...) {
    if (environment %in% search()) {
        while (environment %in% search()) {
            if (!exists("counter", inherits = F)) counter <- 0
            eval(parse(text = paste0("detach(", environment, ")")))
            counter <- counter + 1 
        }
        cat("detached", counter, environment, "s\n")
    } else {cat("no", environment, "attached\n")}
    if (!environment %in% ls(.GlobalEnv, all.names = T)) {
        assign(environment, new.env(), pos = .GlobalEnv)
        cat("created", environment, "\n")
    } else {cat(environment, "already exists\n")}
    sapply(functions, function(func) {
        source(paste0("C:/Users/JT/R/Functions/", func, ".R"))
        eval(parse(text = paste0(environment, "$", func," <- ", func)))
        cat(func, "created in", environment, "\n")
    })
    eval(parse(text = paste0("attach(", environment, ")")))
    cat("attached", environment, "\n\n")
}

关于构造的次优性已经写了很多eval(parse(...))(见这里这里)。但是,我发现的讨论主要涉及子集的替代策略。我的代码中的第一个和第三个实例eval(parse(...))不涉及子集(第二个实例可能与子集有关)。

有没有办法调用new.env(...),[environment name]$[function name] <- [function name]attach(...)不诉诸eval(parse(...))?谢谢。

注意:我不想更改函数的名称.name以将它们隐藏在全局环境中

标签: reval

解决方案


就其价值而言,该函数source实际上使用eval(parse(...))了 ,尽管方式有些微妙。首先,.Internal(parse(...))用于创建表达式,经过更多处理后传递给eval. 所以eval(parse(...))在这种情况下,对于 R 核心团队来说似乎已经足够好了。

也就是说,您无需费劲儿就可以将函数导入新环境。 提供了一个可用于此目的 source的论点。local

local:TRUE、FALSE 或环境,确定解析表达式的评估位置。

一个例子:

env = new.env()
source('test.r', local = env)

测试它的工作原理:

env$test('hello', 'world')
# [1] "hello world"
ls(pattern = 'test')
# character(0)

以及一个使用它的示例test.r文件:

test = function(a,b) paste(a,b)

推荐阅读