如何查看函数的源代码? [英] How can I view the source code for a function?

查看:36
本文介绍了如何查看函数的源代码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想查看一个函数的源代码,看看它是如何工作的.我知道我可以通过在提示符下输入函数名称来打印函数:

I want to look at the source code for a function to see how it works. I know I can print a function by typing its name at the prompt:

> t
function (x) 
UseMethod("t")
<bytecode: 0x2332948>
<environment: namespace:base>

在这种情况下,UseMethod("t") 是什么意思?我如何找到实际使用的源代码,例如:t(1:10)?

In this case, what does UseMethod("t") mean? How do I find the source code that's actually being used by, for example: t(1:10)?

当我看到 UseMethod 和看到 standardGenericshowMethods 时,是否有区别,就像 with>?

Is there a difference between when I see UseMethod and when I see standardGeneric and showMethods, as with 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 函数,但我找不到这些函数的源代码.

In other cases, I can see that R functions are being called, but I can't find the source code for those functions.

> 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 之类的函数?

How do I find functions like .cbindts and .makeNamesTs?

在其他情况下,有一些 R 代码,但大部分工作似乎在其他地方完成.

In still other cases, there's a bit of R code, but most of work seems to be done somewhere else.

> 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.内部.我如何找到这些源代码?

How do I find out what the .Primitive function does? Similarly, some functions call .C, .Call, .Fortran, .External, or .Internal. How can I find the source code for those?

推荐答案

UseMethod("t") 告诉你 t() 是一个 (S3) 具有针对不同对象类的方法的通用函数.

UseMethod("t") is telling you that t() is a (S3) generic function that has methods for different object classes.

对于 S3 类,您可以使用 methods 函数列出特定通用函数或类的方法.

For S3 classes, you can use the methods function to list the methods for a particular generic function or class.

> 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() 很有用,因为您不必知道函数来自哪个包.

"Non-visible functions are asterisked" means the function is not exported from its package's namespace. You can still view its source code via the ::: function (i.e. stats:::t.ts), or by using getAnywhere(). getAnywhere() is useful because you don't have to know which package the function came from.

> 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 函数的例子:

The S4 method dispatch system

The S4 system is a newer method dispatch system and is an alternative to the S3 system. Here is an example of an S4 function:

> 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 方法的方法很有帮助:

The output already offers a lot of information. standardGeneric is an indicator of an S4 function. The method to see defined S4 methods is offered helpfully:

> showMethods(chol2inv)
Function: chol2inv (package base)
x="ANY"
x="CHMfactor"
x="denseMatrix"
x="diagonalMatrix"
x="dtrMatrix"
x="sparseMatrix"

getMethod 可用于查看其中一种方法的源代码:

getMethod can be used to see the source code of one of the methods:

> getMethod("chol2inv", "diagonalMatrix")
Method Definition:

function (x, ...) 
{
    chk.s(...)
    tcrossprod(solve(x))
}
<bytecode: 0x000000000ea2cc70>
<environment: namespace:Matrix>

Signatures:
        x               
target  "diagonalMatrix"
defined "diagonalMatrix"

对于每个方法也有更复杂的签名的方法,例如

There are also methods with more complex signatures for each method, for example

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"

要查看其中一种方法的源代码,必须提供整个签名,例如

To see the source code for one of these methods the entire signature must be supplied, e.g.

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.makeNamesTsstats 中未导出的函数命名空间.您可以使用 :: 运算符或 getAnywhere 查看未导出函数的源代码.

Functions that call unexported functions

In the case of ts.union, .cbindts and .makeNamesTs are unexported functions from the stats namespace. You can view the source code of unexported functions by using the ::: operator or 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 代码.上面输出中的行表示该函数是字节编译的,您仍然可以从R命令行查看源代码.

Functions that call compiled code

Note that "compiled" does not refer to byte-compiled R code as created by the compiler package. The <bytecode: 0x294e410> line in the above output indicates that the function is byte-compiled, and you can still view the source from the R command line.

调用.C.Call.Fortran.External 的函数.Internal.Primitive 在编译代码中调用入口点,因此如果您想完全理解该函数,则必须查看编译代码的来源.这个 R 源代码的 GitHub 镜像是一个不错的起点.函数 pryr::show_c_source 可能是一个有用的工具,因为它会将您直接带到用于 .Internal.Primitive 调用的 GitHub 页面.包可以使用 .C.Call.Fortran.External;但不是 .Internal.Primitive,因为它们用于调用 R 解释器中内置的函数.

Functions that call .C, .Call, .Fortran, .External, .Internal, or .Primitive are calling entry points in compiled code, so you will have to look at sources of the compiled code if you want to fully understand the function. This GitHub mirror of the R source code is a decent place to start. The function pryr::show_c_source can be a useful tool as it will take you directly to a GitHub page for .Internal and .Primitive calls. Packages may use .C, .Call, .Fortran, and .External; but not .Internal or .Primitive, because these are used to call functions built into the R interpreter.

对上述某些函数的调用可能会使用对象而不是字符串来引用已编译的函数.在这些情况下,对象属于 "NativeSymbolInfo""RegisteredNativeSymbol""NativeSymbol" 类;并打印对象会产生有用的信息.例如,optim 调用 .External2(C_optimhess, res$par, fn1, gr1, con)(注意是 C_optimhess,而不是 "C_optimhesis").optim 位于 stats 包中,因此您可以键入 stats::C_optimhess 以查看有关被调用的已编译函数的信息.

Calls to some of the above functions may use an object instead of a character string to reference the compiled function. In those cases, the object is of class "NativeSymbolInfo", "RegisteredNativeSymbol", or "NativeSymbol"; and printing the object yields useful information. For example, optim calls .External2(C_optimhess, res$par, fn1, gr1, con) (note that's C_optimhess, not "C_optimhess"). optim is in the stats package, so you can type stats:::C_optimhess to see information about the compiled function being called.

如果要查看包中的编译代码,则需要下载/解压包源.安装的二进制文件是不够的.软件包的源代码可从最初安装软件包的同一 CRAN(或 CRAN 兼容)存储库中获得.download.packages() 函数可以为你获取包源.

If you want to view compiled code in a package, you will need to download/unpack the package source. The installed binaries are not sufficient. A package's source code is available from the same CRAN (or CRAN compatible) repository that the package was originally installed from. The download.packages() function can get the package source for you.

download.packages(pkgs = "Matrix", 
                  destdir = ".",
                  type = "source")

这将下载Matrix包的源版本并将相应的.tar.gz文件保存在当前目录中.编译函数的源代码可以在解压和解压文件的 src 目录中找到.解压和解压步骤可以在 R 之外完成,也可以在 R 内使用 untar() 函数完成.可以将下载和扩展步骤合并为一个调用(注意,这种方式一次只能下载和解压一个包):

This will download the source version of the Matrix package and save the corresponding .tar.gz file in the current directory. Source code for compiled functions can be found in the src directory of the uncompressed and untared file. The uncompressing and untaring step can be done outside of R, or from within R using the untar() function. It is possible to combine the download and expansion step into a single call (note that only one package at a time can be downloaded and unpacked in this way):

untar(download.packages(pkgs = "Matrix",
                        destdir = ".",
                        type = "source")[,2])

或者,如果包开发是公开托管的(例如通过 GitHubR-ForgeRForge.net),你可能可以在线浏览源代码.

Alternatively, if the package development is hosted publicly (e.g. via GitHub, R-Forge, or RForge.net), you can probably browse the source code online.

某些软件包被视为基础"软件包.这些包与 R 一起提供,并且它们的版本被锁定到 R 的版本.示例包括 basecompilerstatsutils.因此,如上所述,它们不能作为单独的可下载包在 CRAN 上使用.相反,它们是 /src/library/ 下各个包目录中 R 源代码树的一部分.下一节将介绍如何访问 R 源.

Certain packages are considered "base" packages. These packages ship with R and their version is locked to the version of R. Examples include base, compiler, stats, and utils. As such, they are not available as separate downloadable packages on CRAN as described above. Rather, they are part of the R source tree in individual package directories under /src/library/. How to access the R source is described in the next section.

如果您想查看 R 解释器内置的代码,您需要下载/解压 R 源代码;或者您可以通过 R Subversion 存储库Winston Chang 的 github 镜像.

If you want to view the code built-in to the R interpreter, you will need to download/unpack the R sources; or you can view the sources online via the R Subversion repository or Winston Chang's github mirror.

Uwe Ligges 的 R 新闻文章 (PDF) (p. 43) 是如何查看.Internal.Primitive 函数的源代码的很好的通用参考.基本步骤是先在src/main/names.c中查找函数名,然后在src/main/*<中的文件中查找C-entry"名/代码>.

Uwe Ligges's R news article (PDF) (p. 43) is a good general reference of how to view the source code for .Internal and .Primitive functions. The basic steps are to first look for the function name in src/main/names.c and then search for the "C-entry" name in the files in src/main/*.

这篇关于如何查看函数的源代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆