针织品利用代码(在我的例子中是R和LaTEX的组合)生成PDF。可以从子文档中组装文档。
当我现在使用它时,文档是由全局变量组装而成的,每个子文档都被传递到和传递出去。这使得制作意大利面代码变得很容易。
有没有办法使R变量“局部化”到子文档?如何使变量的导出显式化?
我可以在子文档的末尾删除每个局部变量,但我想知道是否有某种合理的形式机制来放松子文档之间的代码耦合。
发布于 2015-12-30 11:37:28
knitr计算公共环境中的所有块(由knit_global()返回)。这是经过设计的;就像源文件中的所有代码都在同一个环境中运行一样,所有块都是在一个公共环境中执行的。这同样适用于儿童文件,因为它们只是主文档的一部分,外化到另一个文件(原则上不是技术上)。
这并不一定会导致意大利面代码:没有什么可以阻止用户在knitr文档中使用函数和其他对象来组织代码/数据。但可能很少有用户这样做,…
因此,对于块/子文档没有封装机制的原因是,它们应该共享一个公共环境,因为它们是一个(主)文档的一部分。
但是,包含子文档的方式可以使用户控制对象、子文档和主文档共享。该解决方案基于函数knit_child(),它非常类似于块选项 child。直接调用knit_child() (相对于通过child选项隐式调用)的优点是可以设置envir参数,该参数定义了“要计算代码块的环境”(来自?knit)。
围绕knit_child(),我编写了包装器IsolatedChild来简化事情:
IsolatedChild <- function(input, ...) {
evaluationEnv <- list2env(x = list(...), parent = as.environment(2))
cat(asis_output(knit_child(input = input, envir = evaluationEnv, quiet = TRUE)))
return(evaluationEnv)
}传递给...的参数将在子文档中可用。(请给出它们的名称,参见下面的示例。)函数返回计算子文档的环境。
在parent中指定list2env是至关重要的,我根据这个答案选择了as.environment(2)。否则,parent将默认为parent.frame(),从而向子文档公开knit_global()中的对象。
assign可用于使从IsolatedChild返回的对象在全局环境中可用。
注意围绕cat(asis_output())的knit_child构造,它确保子文档的输出正确地包含在主文档中,而不管当前块中的results设置如何。
在谈到这个例子之前,最后的两点意见是:
knit子文档,并使用\include{}将其包含在主文档中。knitr选项。此外,这两个文档都可以通过副作用(options()、par()、打开设备、.)进行交互。下面是一个完整的示例/演示:
inputNormal没有什么特别之处,它只是对正常行为的一种展示。inputHidden演示了IsolatedChild()的用法,将两个变量传递给子文档。IsolatedChild()返回这两个值以及在子对象中创建的第三个对象。check演示了传递给/创建在“孤立子环境”中的对象不会污染全局环境。import展示了如何使用assign从“孤立子环境”“导入”对象到全局环境。
main.Rnw**:**
\documentclass{article}
\begin{document}
<<setup>>=
library(knitr)
objInMain <- TRUE
IsolatedChild <- function(input, ...) {
evaluationEnv <- list2env(x = list(...), parent = as.environment(2))
cat(asis_output(knit_child(input = input, envir = evaluationEnv, quiet = TRUE)))
return(evaluationEnv)
}
@
<<inputNormal, child="child_normal.Rnw">>=
@
<<inputHidden, results = "asis">>=
returned <- IsolatedChild(input = "child_hidden.Rnw",
passedValue = 42,
otherPassedValue = 3.14)
cat(sprintf("Returned from hidden child: \\texttt{%s}",
paste(ls(returned), collapse = ", ")))
@
<<check, results = "asis">>=
cat(sprintf("In global evaluation environment: \\texttt{%s}",
paste(ls(), collapse = ", ")))
@
<<import, results = "asis">>=
assign("objInChildHidden", returned$objInChildHidden)
cat(sprintf("In global evaluation environment: \\texttt{%s}",
paste(ls(), collapse = ", ")))
@
\end{document}
child_normal.Rnw**:**
<<inChildNormal>>=
objInChildNormal <- TRUE # visible in main.Rnw (standard behaviour)
@
child_hidden.Rnw**:**
Text in \texttt{child\_hidden.Rnw}.
<<inChildHidden>>=
objInChildHidden <- TRUE
print(sprintf("In hidden child: %s",
paste(ls(), collapse = ", ")))
# Returns FALSE.
# Would be TRUE if "parent" weren't specifiet in list2env().
exists("objInMain", inherits = TRUE)
@
main.pdf**:**

https://stackoverflow.com/questions/34498734
复制相似问题