and*_*ewH 5 version-control comments r help-system
getAnywhere() 是否有任何相当简单、直接的函数,它返回带有任何注释的函数的源代码,这样,如果我没有看到注释,我可以确信没有注释,无论代码是否在 R 中, c、c++、Fortran 还是其他?例如,stats:::plot.acf 中似乎没有任何注释。我是否可以由此得出结论,其案文没有评论?
我知道有一个类似流程图的搜索过程,如果您知道源代码是用 R 编写的,那么可以通过某种适当的搜索方法 tp gethub 从特定的 github 存储库中获取包含注释的源代码。此外,如果您确定代码采用某种指定的其他语言,则可以通过更复杂的搜索过程来使用它,该过程包括查找正确的文件,然后在其中进行文本搜索,这对于基本包和贡献包来说是不同的。我的印象是,至少直到最近,如果您想了解是否存在包含注释的代码版本,则没有捷径可以通过隐式流程图搜索方法来学习和工作。此外,我相信,除了注释本身或先验知识之外,没有任何地方可以识别包含或不包含注释的代码版本。
然而,R 是一个发展相当迅速的生态系统,我认为现在可能存在更简单的工具来确定是否存在包含注释的源版本,并查找它(如果有),这并不是完全没有道理的。他们有吗?
R 函数的源代码是否在内部保留(通过其srcref
属性)取决于keep.source
定义函数时 option 的值。我所说的源代码,是指用户输入的代码,带有注释、可能不一致的缩进、可能不一致的运算符周围的间距等。
options(keep.source = FALSE)\nf <- function(x) {\n ## A comment\n x +\n 1}\n\ngetSrcref(f)\n## NULL # (invisibly)\n\ndeparse(f, control = "all")\n## [1] "function (x) "\n## [2] "{" \n## [3] " x + 1" \n## [4] "}" \n
Run Code Online (Sandbox Code Playgroud)\noptions(keep.source = TRUE)\ng <- function(x) {\n ## A comment\n x +\n 1}\n\ngetSrcref(g)\n## function(x) {\n## ## A comment\n## x +\n## 1}\n\ndeparse(g, control = "all")\n## [1] "function(x) {" \n## [2] " ## A comment"\n## [3] " x +" \n## [4] " 1}"\n
Run Code Online (Sandbox Code Playgroud)\n贡献的包中的函数是否保留其源代码取决于R CMD INSTALL
从源(由您或 CRAN)构建包时传递到的选项。默认情况下是放弃源代码,但您可以通过从源安装并设置标志来避免这种情况--with-keep.source
:
install.packages(pkgs, type = "source", INSTALL_opts = "--with-keep.source")\n
Run Code Online (Sandbox Code Playgroud)\n基础包(base
、stats
等)中的函数不会有源代码,除非您从环境变量R_KEEP_PKG_SOURCE
设置为yes
\xe2\x80\x94 的源代码构建 R 本身,至少,这是我从?options
. 要了解如何构建 R,请参阅相应的手册。
给定一个带有源引用的函数,您可以以编程方式从源代码中提取注释。一种快速但肮脏的方法是模式匹配:
\nzzz <- deparse(g, control = "all")\ngrep("#", zzz, value = TRUE)\n## [1] " ## A comment"\n
Run Code Online (Sandbox Code Playgroud)\n不过,可能会出现误报,因为该模式#
还匹配包含哈希字符的字符串和非语法名称,而这些名称根本不是注释。
grep("#", "\\"## Not a comment\\"", value = TRUE)\n## [1] "\\"## Not a comment\\""\n
Run Code Online (Sandbox Code Playgroud)\n提取注释的一种更可靠的方法是检查解析数据中类型标记COMMENT
:
getParseData(parse(text = zzz), includeText = NA)\n## line1 col1 line2 col2 id parent token terminal text\n## 23 1 1 4 4 23 0 expr FALSE \n## 1 1 1 1 8 1 23 FUNCTION TRUE function\n## 2 1 9 1 9 2 23 \'(\' TRUE (\n## 3 1 10 1 10 3 23 SYMBOL_FORMALS TRUE x\n## 4 1 11 1 11 4 23 \')\' TRUE )\n## 20 1 13 4 4 20 23 expr FALSE \n## 6 1 13 1 13 6 20 \'{\' TRUE {\n## 8 2 5 2 16 8 20 COMMENT TRUE ## A comment\n## 17 3 9 4 3 17 20 expr FALSE \n## 10 3 9 3 9 10 12 SYMBOL TRUE x\n## 12 3 9 3 9 12 17 expr FALSE \n## 11 3 11 3 11 11 17 \'+\' TRUE +\n## 14 4 3 4 3 14 15 NUM_CONST TRUE 1\n## 15 4 3 4 3 15 17 expr FALSE \n## 16 4 4 4 4 16 20 \'}\' TRUE }\n
Run Code Online (Sandbox Code Playgroud)\n显然,getParseData
返回的信息比您需要的多得多。您可以使用以下实用程序,它将带有源引用的函数作为参数,并返回列出注释(如果有)的字符向量:
getComments <- function(func) {\n func <- match.fun(func)\n if (is.null(getSrcref(func))) {\n stop("\'func\' has no source references")\n }\n data <- getParseData(func, includeText = NA) \n if (is.null(data)) {\n op <- options(keep.source = TRUE, keep.parse.data = TRUE)\n on.exit(options(op))\n expr <- parse(text = deparse(func, control = "all"))\n data <- getParseData(expr, includeText = NA)\n }\n data$text[data$token == "COMMENT"]\n}\n
Run Code Online (Sandbox Code Playgroud)\ngetComments(g)\n## [1] "## A comment"\n\nh <- function(x) {\n ## I will comment\n ## anywhere\n ######## and with as many hashes\n x + 1 # as I want!\n}\n\ngetComments(h)\n## [1] "## I will comment" \n## [2] "## anywhere" \n## [3] "######## and with as many hashes"\n## [4] "# as I want!"\n\n## You will need Rtools on Windows and Command Line Tools on macOS\n## to install from sources packages containing C/C++/Fortran code.\n## \'lme4\' is one such package ... feel free to choose a different one.\ninstall.packages("lme4", type = "source", INSTALL_opts = "--with-keep.source")\ngetComments(lme4::lmer)\n## [1] "## , ...)" \n## [2] "## see functions in modular.R for the body .." \n## [3] "## back-compatibility kluge" \n## [4] "## if (!is.null(list(...)[[\\"family\\"]])) {" \n## [5] "## warning(\\"calling lmer with \'family\' is deprecated; please use glmer() instead\\")"\n## [6] "## mc[[1]] <- quote(lme4::glmer)" \n## [7] "## if(missCtrl) mc$control <- glmerControl()" \n## [8] "## return(eval(mc, parent.frame(1L)))" \n## [9] "## }" \n## [10] "## update for back-compatibility kluge" \n## [11] "## https://github.com/lme4/lme4/issues/50" \n## [12] "## parse data and formula" \n## [13] "## create deviance function for covariance parameters (theta)" \n## [14] "## optimize deviance function over covariance parameters" \n## [15] "## prepare output"\n
Run Code Online (Sandbox Code Playgroud)\nAFAIK,没有方便的机制来检查 R 函数调用的 C 代码在编译之前是否包含注释......
\n一如既往,相关文档有点分散。我发现这些帮助页面很有用:?parse
、?deparse
、?.deparseOpts
、?srcref
(以及其中的链接)、?options
和?getParseData
。