你如何打印 R 列表数据,以便它可以作为代码进行评估?

How do you print R list data so that it can be evaluated as code?

您将如何获取嵌套 R 列表的树,并以可以将它们作为代码计算的方式打印它们?

例如,假设我们有以下列表代码:

spec <- list(
  description="An mtcards example",
  data = list(),
  mark = "point",
  encoding = list(
    x = list(field = "wt", type="quantitative"),
    y = list(field="mpg", type="quantitative"), 
    color = list(field="cyl", type="nominal")))

是否有一个函数 f(在标准库中,或者在 CRAN 中的某处)使得 f(spec) 生成一个字符串,看起来或多或少类似于用于定义 [=15 的代码=],最好根据行的长度进行合理的缩进?类似于:

'list(
  description="An mtcards example",
  data = list(),
  mark = "point",
  encoding = list(
    x = list(field = "wt", type="quantitative"),
    y = list(field="mpg", type="quantitative"), 
    color = list(field="cyl", type="nominal")))'

这在其他语言中是可能的,例如 JS、Python 和 Clojure。通常,数据结构打印为文字,可以通过手头的语言进行评估。还有用于缩进的特殊功能(“漂亮的打印”,我们通常称之为)。但是我不记得在 R 中遇到过这样的事情(尽管我已经很多年没有广泛使用它了),而且 Google 已经证明在打开任何东西时都是无用的。

就上下文而言,现在正在考虑制作 automatic translations of Vega-Lite/Vega examples in other languages (which is easy for Clojure EDN data representations), but it's not clear how we'd do this for R data specifications as used by vegawidget。有没有人知道我们如何做到这一点,或者受到启发来编写代码来手工完成?

谢谢!


更新:有人指出deparse(和dput)让我们很接近这里,但他们仍然没有输出那种您希望在实际代码中看到的缩进。特别是,对于这个例子,我得到:

> dput(spec)
list(description = "An mtcards example", data = list(), mark = "point",
    encoding = list(x = list(field = "wt", type = "quantitative"),
        y = list(field = "mpg", type = "quantitative"), color = list(
            field = "cyl", type = "nominal")))

特别是,我希望除非必要,否则不要在列表定义的中间断行; color = ... 应该在此处独占一行。对于顶层 list(...) 中的一些其他条目位于同一行,而其他条目则分开,我并不感到兴奋,但我们可能会接受它作为示例。尽管在代码文档中,我永远不会期望看到 color = ... 列表像那样被打破,所以这并不能完全解决问题,除非有人有更好的解决方案。

再次感谢!

函数 dput 是我们将 R 对象转换为文本字符串的标准方法,当 运行 在 R 控制台中时,该函数将重现该对象。事实上,它在 Stack Overflow 上的 R 标签中发布问题和答案时使用得非常频繁。例如:

x <- list(a = 1, b = "2")
dput(x)
#> list(a = 1, b = "2")

但是,dput 并不总能提供美观的输出。听起来您正在寻找的是 dput 与代码美化器的组合。

Base R 没有代码美化器。撇开其他不谈,使代码漂亮的因素是相当主观的,并且与大多数编程语言一样,R 作者没有规定合法代码的 布局

但是,R 有一些可用的包可以美化代码,这些包可以用于 dput 的输出。例如,我们可以编写这样的函数:

f <- function(x) {
  text_con <- textConnection("output", "w")
  dput(x, text_con)
  close(text_con)
  formatR::tidy_source(text = output, args.newline = TRUE, width = 40)
}

这是一种美化dput:

f(spec)
#> list(
#>     description = "An mtcards example", data = list(),
#>     mark = "point", encoding = list(
#>         x = list(field = "wt", type = "quantitative"),
#>         y = list(field = "mpg", type = "quantitative"),
#>         color = list(field = "cyl", type = "nominal")
#>     )
#> )