我想查看一个函数的源代码,看看它是如何工作的 . 我知道我可以通过在提示符下键入其名称来打印函数:
> t
function (x)
UseMethod("t")
<bytecode: 0x2332948>
<environment: namespace:base>
在这种情况下, UseMethod("t")
是什么意思?如何查找实际使用的源代码,例如: t(1:10)
?
当我看到 UseMethod
和我看到 standardGeneric
和 showMethods
时,和 with
之间有区别吗?
> with
standardGeneric for "with" defined from package "base"
function (data, expr, ...)
standardGeneric("with")
<bytecode: 0x102fb3fc0>
<environment: 0x102fab988>
Methods may be defined for arguments: data
Use showMethods("with") for currently available ones.
在其他情况下,我可以看到正在调用R函数,但我找不到这些函数的源代码 .
> ts.union
function (..., dframe = FALSE)
.cbind.ts(list(...), .makeNamesTs(...), dframe = dframe, union = TRUE)
<bytecode: 0x36fbf88>
<environment: namespace:stats>
> .cbindts
Error: object '.cbindts' not found
> .makeNamesTs
Error: object '.makeNamesTs' not found
我如何找到像 .cbindts
和 .makeNamesTs
这样的函数?
在其他情况下,有一些R代码,但大多数工作似乎是在其他地方完成的 .
> matrix
function (data = NA, nrow = 1, ncol = 1, byrow = FALSE, dimnames = NULL)
{
if (is.object(data) || !is.atomic(data))
data <- as.vector(data)
.Internal(matrix(data, nrow, ncol, byrow, dimnames, missing(nrow),
missing(ncol)))
}
<bytecode: 0x134bd10>
<environment: namespace:base>
> .Internal
function (call) .Primitive(".Internal")
> .Primitive
function (name) .Primitive(".Primitive")
如何找出 .Primitive
函数的作用?同样,某些函数调用 .C
, .Call
, .Fortran
, .External
或 .Internal
. 我如何找到这些的源代码?
9 回答
除了这个问题及其重复的其他答案之外,这里有's a good way to get source code for a package function without needing to know which package it' s . 如果我们想要
randomForest::rfcv()
的来源:要 view/edit 它在弹出窗口中:
至 redirect to a separate file :
对于非原始函数,R base包含一个函数
body()
,它返回函数体 . 例如,可以查看print.Date()
函数的来源:会产生这个:
如果您正在使用脚本并希望将函数代码作为字符向量,则可以获取它 .
会得到你:
我为什么要做这样的事情?我正在基于列表创建自定义S3对象(
x
,其中class(x) = "foo"
) . 其中一个列表成员(名为"fun")是一个函数,我希望print.foo()
显示函数源代码,缩进 . 所以我在print.foo()
中得到了以下代码:缩进并显示与
x[["fun"]]
关联的代码 .您也可以尝试使用
print.function()
(S3泛型)来在控制台中编写函数 .R
edit
有一个非常方便的功能它将使用R的
options
中指定的编辑器打开optim
的源代码,然后您可以编辑它并将修改后的函数分配给new_optim
. 我非常喜欢这个函数来查看代码或调试代码,例如,打印一些消息或变量,甚至将它们分配给全局变量以供进一步调查(当然你可以使用debug
) .如果您只想查看源代码并且不希望在控制台上打印恼人的长源代码,则可以使用
显然,这不能用于查看C / C或Fortran源代码 .
BTW,
edit
可以打开其他对象,如列表,矩阵等,然后显示具有属性的数据结构 . 函数de
可用于打开类似编辑器的excel(如果GUI支持它)来修改矩阵或数据框并返回新的 . 这有时很方便,但在通常情况下应该避免,特别是当矩阵很大时 .View([function_name])
- 例如 .View(mean)
确保使用大写[V] . 只读代码将在编辑器中打开 .UseMethod("t")
告诉您t()
是一个(S3)泛型函数,它具有不同对象类的方法 .S3方法调度系统
对于S3类,可以使用
methods
函数列出特定泛型函数或类的方法 ."Non-visible functions are asterisked"表示该函数未从其包的名称空间中导出 . 您仍然可以通过
:::
函数(即stats:::t.ts
)或使用getAnywhere()
查看其源代码 .getAnywhere()
很有用,因为您不必知道函数来自哪个包 .S4方法调度系统
S4系统是一种较新的方法调度系统,是S3系统的替代方案 . 以下是S4功能的示例:
输出已经提供了很多信息 .
standardGeneric
是S4功能的指示器 . 有用地提供了查看定义的S4方法的方法:getMethod
可用于查看其中一种方法的源代码:例如,对于每种方法,还存在具有更复杂签名的方法
要查看其中一种方法的源代码,必须提供整个签名,例如
提供部分签名是不够的
调用未导出函数的函数
在
ts.union
的情况下,.cbindts
和.makeNamesTs
是stats
命名空间中的未导出函数 . 您可以使用:::
运算符或getAnywhere
查看未导出函数的源代码 .调用编译代码的函数
请注意,"compiled"不引用由 compiler 包创建的字节编译的R代码 . 上面输出中的
<bytecode: 0x294e410>
行表示该函数是字节编译的,您仍然可以从R命令行查看源 .调用
.C
,.Call
,.Fortran
的函数,.External
,.Internal
或.Primitive
正在编译代码中调用入口点,因此如果要完全理解该函数,则必须查看已编译代码的源代码 . This R源代码的GitHub镜像是一个不错的起点 . 函数pryr::show_c_source
可以是一个有用的工具,因为它可以直接到达.Internal
和.Primitive
调用的GitHub页面 . 包可以使用.C
,.Call
,.Fortran
和.External
;但不是.Internal
或.Primitive
,因为它们用于调用内置于R解释器中的函数 .调用上述某些函数可能会使用对象而不是字符串来引用已编译的函数 . 在这些情况下,对象属于
"NativeSymbolInfo"
,"RegisteredNativeSymbol"
或"NativeSymbol"
类;并打印对象产生有用的信息 . 例如,optim
调用.External2(C_optimhess, res$par, fn1, gr1, con)
(注意C_optimhess
,而不是"C_optimhess"
) .optim
在stats包中,因此您可以键入stats:::C_optimhess
以查看有关正在调用的已编译函数的信息 .包中的编译代码
如果要查看包中的已编译代码,则需要下载/解压缩包源 . 安装的二进制文件是不够的 . 软件包的源代码可从最初安装软件包的相同CRAN(或CRAN兼容)存储库中获得 .
download.packages()
函数可以为您获取包源 .这将下载Matrix包的源版本并将相应的
.tar.gz
文件保存在当前目录中 . 已编译函数的源代码可以在未压缩和未解压缩文件的src
目录中找到 . 解压缩和解除步骤可以在R
之外完成,或者在R
之内使用untar()
函数完成 . 可以将下载和扩展步骤组合到一个调用中(请注意,一次只能下载一个包并以这种方式解压缩):或者,如果包开发是公开托管的(例如,通过GitHub,R-Forge或RForge.net),您可以在线浏览源代码 .
基础包中的编译代码
某些包被认为是"base"包 . 这些软件包附带R,其版本锁定为R版本 . 示例包括
base
,compiler
,stats
和utils
. 因此,如上所述,它们不能作为CRAN上的单独可下载包提供 . 相反,它们是/src/library/
下各个包目录中R源代码树的一部分 . 如何访问R源将在下一节中介绍 .内置于R解释器中的编译代码
如果要查看R解释器内置的代码,则需要下载/解压缩R源代码;或者您可以通过R Subversion repository或Winston Chang's github mirror在线查看来源 .
Uwe Ligges的R news article (PDF)(第43页)是如何查看
.Internal
和.Primitive
函数源代码的一般参考 . 基本步骤是首先在src/main/names.c
中查找函数名称,然后在src/main/*
中的文件中搜索"C-entry"名称 .只要该函数是用纯R而不是C / C / Fortran编写的,就可以使用以下内容 . 否则最好的方法是 debugging 并使用“ jump into ”:
使用debug()函数进行调试时会显示它 . 假设您想在t()转置函数中查看底层代码 . 只需键入't',就不会显示太多内容 .
但是,使用'debug(functionName)',它揭示了底层代码,没有内部 .
EDIT: debugonce()完成相同操作而不必使用undebug()
没有看到这是如何适应主要答案的流程但它让我困扰了一段时间所以我在这里添加它:
中缀运营商
要查看某些基础中缀运算符的源代码(例如,
%%
,%*%
,%in%
),请使用getAnywhere
,例如:主要答案包括如何使用镜子深入挖掘 .