我如何查看函数的源代码?
我想看看函数的源代码,看看它是如何工作的。 我知道我可以通过在提示符处输入它的名字来打印一个函数:
> t
function (x)
UseMethod("t")
<bytecode: 0x2332948>
<environment: namespace:base>
在这种情况下, UseMethod("t")
是什么意思? 我如何找到实际使用的源代码,例如: t(1:10)
?
在其他情况下,我可以看到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
。 我如何找到这些源代码?
UseMethod("t")
告诉你t()
是一个(S3)泛型函数,它具有用于不同对象类的方法。
S3方法调度系统
对于S3类,可以使用methods
函数列出特定通用函数或类的方法。
> methods(t)
[1] t.data.frame t.default t.ts*
Non-visible functions are asterisked
> methods(class="ts")
[1] aggregate.ts as.data.frame.ts cbind.ts* cycle.ts*
[5] diffinv.ts* diff.ts kernapply.ts* lines.ts
[9] monthplot.ts* na.omit.ts* Ops.ts* plot.ts
[13] print.ts time.ts* [<-.ts* [.ts*
[17] t.ts* window<-.ts* window.ts*
Non-visible functions are asterisked
“不可见函数被星号标记”表示函数不从其包的名称空间导出。 您仍然可以通过:::
函数(即stats:::t.ts
)或使用getAnywhere()
查看其源代码。 getAnywhere()
很有用,因为您不必知道函数来自哪个包。
> getAnywhere(t.ts)
A single object matching ‘t.ts’ was found
It was found in the following places
registered S3 method for t from namespace stats
namespace:stats
with value
function (x)
{
cl <- oldClass(x)
other <- !(cl %in% c("ts", "mts"))
class(x) <- if (any(other))
cl[other]
attr(x, "tsp") <- NULL
t(x)
}
<bytecode: 0x294e410>
<environment: namespace:stats>
S4方法调度系统
S4系统是一种较新的方法调度系统,是S3系统的替代方案。 这是一个S4函数的例子:
> library(Matrix)
Loading required package: lattice
> chol2inv
standardGeneric for "chol2inv" defined from package "base"
function (x, ...)
standardGeneric("chol2inv")
<bytecode: 0x000000000eafd790>
<environment: 0x000000000eb06f10>
Methods may be defined for arguments: x
Use showMethods("chol2inv") for currently available ones.
输出已经提供了很多信息。 standardGeneric
是S4函数的一个指标。 有助于看到定义的S4方法的方法:
> showMethods(chol2inv)
Function: chol2inv (package base)
x="ANY"
x="CHMfactor"
x="denseMatrix"
x="diagonalMatrix"
x="dtrMatrix"
x="sparseMatrix"
getMethod
可以用来查看其中一个方法的源代码:
> getMethod("chol2inv", "diagonalMatrix")
Method Definition:
function (x, ...)
{
chk.s(...)
tcrossprod(solve(x))
}
<bytecode: 0x000000000ea2cc70>
<environment: namespace:Matrix>
Signatures:
x
target "diagonalMatrix"
defined "diagonalMatrix"
例如,每种方法也有更复杂的签名方法
require(raster)
showMethods(extract)
Function: extract (package raster)
x="Raster", y="data.frame"
x="Raster", y="Extent"
x="Raster", y="matrix"
x="Raster", y="SpatialLines"
x="Raster", y="SpatialPoints"
x="Raster", y="SpatialPolygons"
x="Raster", y="vector"
要查看这些方法之一的源代码,必须提供整个签名,例如
getMethod("extract" , signature = c( x = "Raster" , y = "SpatialPolygons") )
提供部分签名是不够的
getMethod("extract",signature="SpatialPolygons")
#Error in getMethod("extract", signature = "SpatialPolygons") :
# No method found for function "extract" and signature SpatialPolygons
调用未导出函数的函数
在ts.union
的情况下, .cbindts
和.makeNamesTs
是来自stats
名称空间的未导出函数。 您可以使用:::
运算符或getAnywhere
来查看未导出函数的源代码。
> stats:::.makeNamesTs
function (...)
{
l <- as.list(substitute(list(...)))[-1L]
nm <- names(l)
fixup <- if (is.null(nm))
seq_along(l)
else nm == ""
dep <- sapply(l[fixup], function(x) deparse(x)[1L])
if (is.null(nm))
return(dep)
if (any(fixup))
nm[fixup] <- dep
nm
}
<bytecode: 0x38140d0>
<environment: namespace:stats>
调用编译代码的函数
请注意,“编译”不会引用由编译器包创建的字节编译的R代码。 上述输出中的<bytecode: 0x294e410>
行表示该函数是字节编译的,您仍然可以从R命令行查看源文件。
调用函数.C
, .Call
, .Fortran
, .External
, .Internal
,或.Primitive
在编译的代码调用入口点,所以你必须看看编译代码的来源,如果你想充分了解该功能。 这个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()
函数可以为您获取软件包源代码。
download.packages(pkgs = "Matrix",
destdir = ".",
type = "source")
这将下载Matrix版本的源代码包并将相应的.tar.gz
文件保存在当前目录中。 已编译函数的源代码可以在未压缩和未压缩文件的src
目录中找到。 解压缩和解压缩步骤可以在R
之外完成,也可以在R
之内使用untar()
函数完成。 可以将下载和扩展步骤合并为一次调用(请注意,一次只能下载和解包一个包):
untar(download.packages(pkgs = "Matrix",
destdir = ".",
type = "source")[,2])
或者,如果软件包开发是公开托管的(例如,通过GitHub,R-Forge或RForge.net),则可以在线浏览源代码。
在基础包中编译代码
某些软件包被视为“基础”软件包。 这些软件包随附R,并且它们的版本被锁定为R的版本。示例包括base
, compiler
, stats
和utils
。 因此,如上所述,它们在CRAN上不能作为单独的可下载软件包提供。 相反,它们是/src/library/
下独立包目录中R源树的一部分。 下一节将介绍如何访问R源。
编译内置在R解释器中的代码
如果您想查看R解释器的内置代码,您需要下载/解压缩R源代码; 或者您可以通过R Subversion版本库或Winston Chang的github镜像在线查看源代码。
Uwe Ligges的R新闻文章(PDF)(第43页)是如何查看.Internal
和.Primitive
函数源代码的很好的一般参考。 基本步骤是首先在src/main/names.c
查找函数名称,然后在src/main/*
文件中搜索“C-entry”名称。
除了这个问题及其重复的其他答案之外,这里有一个获取包函数源代码的好方法,而不需要知道它包含哪个包。例如,如果我们需要randomForest::rfcv()
的源代码:
在弹出窗口中查看/编辑它:
edit(getAnywhere('rfcv'), file='source_rfcv.r')
要重定向到一个单独的文件 :
capture.output(getAnywhere('rfcv'), file='source_rfcv.r')
它在使用debug()函数进行调试时显示。 假设你想在t()转置函数中看到底层代码。 只要输入't',不会透露太多。
>t
function (x)
UseMethod("t")
<bytecode: 0x000000003085c010>
<environment: namespace:base>
但是,使用'调试(函数名)',它揭示了底层代码,没有内部。
> debug(t)
> t(co2)
debugging in: t(co2)
debug: UseMethod("t")
Browse[2]>
debugging in: t.ts(co2)
debug: {
cl <- oldClass(x)
other <- !(cl %in% c("ts", "mts"))
class(x) <- if (any(other))
cl[other]
attr(x, "tsp") <- NULL
t(x)
}
Browse[3]>
debug: cl <- oldClass(x)
Browse[3]>
debug: other <- !(cl %in% c("ts", "mts"))
Browse[3]>
debug: class(x) <- if (any(other)) cl[other]
Browse[3]>
debug: attr(x, "tsp") <- NULL
Browse[3]>
debug: t(x)
编辑: debugonce()完成相同,而不必使用undebug()
链接地址: http://www.djcxy.com/p/4247.html