首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在针织子文档中隐藏和传递变量?

如何在针织子文档中隐藏和传递变量?
EN

Stack Overflow用户
提问于 2015-12-28 18:28:05
回答 1查看 2.8K关注 0票数 16

针织品利用代码(在我的例子中是R和LaTEX的组合)生成PDF。可以从子文档中组装文档。

当我现在使用它时,文档是由全局变量组装而成的,每个子文档都被传递到和传递出去。这使得制作意大利面代码变得很容易。

有没有办法使R变量“局部化”到子文档?如何使变量的导出显式化?

我可以在子文档的末尾删除每个局部变量,但我想知道是否有某种合理的形式机制来放松子文档之间的代码耦合。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-12-30 11:37:28

knitr计算公共环境中的所有块(由knit_global()返回)。这是经过设计的;就像源文件中的所有代码都在同一个环境中运行一样,所有块都是在一个公共环境中执行的。这同样适用于儿童文件,因为它们只是主文档的一部分,外化到另一个文件(原则上不是技术上)。

这并不一定会导致意大利面代码:没有什么可以阻止用户在knitr文档中使用函数和其他对象来组织代码/数据。但可能很少有用户这样做,…

因此,对于块/子文档没有封装机制的原因是,它们应该共享一个公共环境,因为它们是一个(主)文档的一部分。

但是,包含子文档的方式可以使用户控制对象、子文档和主文档共享。该解决方案基于函数knit_child(),它非常类似于块选项 child。直接调用knit_child() (相对于通过child选项隐式调用)的优点是可以设置envir参数,该参数定义了“要计算代码块的环境”(来自?knit)。

围绕knit_child(),我编写了包装器IsolatedChild来简化事情:

代码语言:javascript
复制
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**:**

代码语言:javascript
复制
\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**:**

代码语言:javascript
复制
<<inChildNormal>>=
objInChildNormal <- TRUE # visible in main.Rnw (standard behaviour)
@

child_hidden.Rnw**:**

代码语言:javascript
复制
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**:**

票数 18
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34498734

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档