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

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

问题描述

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

 > t 
函数(x)
UseMethod(t)
<字节码:0x2332948>
< environment:namespace:base>

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



在其他情况下,我可以看到R函数被调用,但我找不到这些函数的源代码。

 > ts.union 
函数(...,dframe = FALSE)
.cbind.ts(list(...),.makeNamesTs(...),dframe = dframe,union = TRUE)
<字节码:0x36fbf88>
< environment:namespace:stats>
> .cbindts
错误:找不到对象'.cbindts'
> .makeNamesTs
Error:object'.makeNamesTs'not found

如何找到像 .cbindts .makeNamesTs



例如,有一些R代码,但大部分工作似乎是在别的地方完成的。

 >矩阵
函数(data = NA,nrow = 1,ncol = 1,byrow = FALSE,dimnames = NULL)
{
if(is.object(data)||!is.atomic (数据))
数据< - as.vector(数据)
。内部(矩阵(数据,nrow,ncol,byrow,dimnames,缺失(nrow),
缺失(ncol) ))
}
<字节码:0x134bd10>
< environment:namespace:base>
> 。内部
函数(调用).Primitive(。Internal)
> .Primitive
函数(名称).Primitive(。Primitive)

我如何找出 .Primitive 函数的作用是什么?类似地,一些函数调用 .C .Call .Fortran .External .Internal 。如何找到这些源代码?

解决方案

UseMethod(t)告诉你 t()是一个( S3 < a>)具有不同对象类方法的泛型函数。

S3方法调度系统



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

 >方法(t)
[1] t.data.frame t.default t.ts *

不可见函数带星号
>方法(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 *

不可见函数带星号

不可见函数被星号标记表示该函数不从其包的名称空间导出。您仍然可以通过 ::: 函数(即 stats ::: t.ts )查看其源代码,或者使用 getAnywhere() getAnywhere()很有用,因为您不必知道该函数来自哪个包。

 > getAnywhere(t.ts)
找到与't.ts'匹配的单个对象
在以下位置找到
从名称空间统计信息中注册了t的S3方法
名称空间: (x)
{
cl < - oldClass(x)
其他< - !(cl%in%)



$ c(ts,mts))
class(x)< - if(any(other))
cl [other]
attr(x,tsp)< ; - NULL
t(x)
}
<字节码:0x294e410>
< environment:namespace:stats>



S4方法调度系统



S4系统是一种较新的方法调度系统,是S3系统的替代方案。下面是一个S4函数的例子:

 >库(Matrix)
加载所需包:lattice
> chol2inv
standardgeneric(chol2inv)
<字节码: 0x000000000eafd790>
<环境:0x000000000eb06f10>
可以为参数定义方法:x
将showMethods(chol2inv)用于当前可用的方法。

输出已经提供了很多信息。 standardGeneric 是S4函数的一个指标。

 > showMethods(chol2inv)
函数:chol2inv(包基数)
x =ANY
x =CHMfactor
x =denseMatrix
x =diagonalMatrix
x =dtrMatrix
x =sparseMatrix

getMethod 可以用来查看其中一个方法的源代码:

 > getMethod(chol2inv,diagonalMatrix)
方法定义:

函数(x,...)
{
chk.s(...)
tcrossprod(solve(x))
}
<字节码:0x000000000ea2cc70>
< environment:namespace:Matrix>

签名:
x
targetdiagonalMatrix
defineddiagonalMatrix

每种方法都有更复杂的签名方法,例如

  require(raster )
showMethods(提取)
函数:extract(包光栅)
x =Raster,y =data.frame
x =Raster,y =Extent
x =栅格,y =矩阵
x =栅格,y =SpatialLines
x =栅格,y =SpatialPoints
x = ,y =SpatialPolygons
x =Raster,y =vector

请参阅这些方法之一的源代码必须提供整个签名,例如

  getMethod(extract,signature = c (x =Raster,y =SpatialPolygons))

不足以提供部分签名

  getMethod(extract,signature =SpatialPolygons)
getMethod(extract ,签名= SpatialPolygons):
#未找到函数extract和signature的方法SpatialPolygons



函数调用未导出的函数



对于 ts.union .cbindts .makeNamesTs 是来自 stats 命名空间的未导出函数。您可以使用 ::: 运算符或 getAnywhere 来查看未导出函数的源代码。

 > stats :::。makeNamesTs 
function(...)
{
l < - as.list(substitute(list(...)))[ - 1L]
nm < - 名称(l)
修正< - 如果(is.null(nm))
seq_along(l)
else nm ==
dep< (b)如果(空)(nm))
返回(dep)
if(any(fixup),function(x)deparse(x)[1L])
))
nm [fixup]< - dep
nm
}
<字节码:0x38140d0>
< environment:namespace:stats>



调用编译代码的函数



注意编译并不涉及由编译器包创建的字节编译的R代码。上面输出中的<字节码:0x294e410> 行表明该函数是字节编译的,您仍然可以从R命令行查看源代码。



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



调用上述某些函数可能会使用一个对象而不是字符串来引用已编译的函数。在这些情况下,对象是类NativeSymbolInfoRegisteredNativeSymbol 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 编译器 stats utils 。因此,如上所述,它们在CRAN上不能作为单独的可下载软件包提供。相反,它们是 / src / library / 下个别包目录中R源树的一部分。如何访问R源将在下一节中介绍。



内置于R解释器中的编译代码



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



Uwe Ligges's R新闻报道(PDF)(第43页)是一个如何查看 .Internal .Primitive 函数的源代码。基本步骤是首先在 src / main / names.c 中查找函数名称,然后在<$ c中的文件中搜索C-entry名称$ c> src / main / *


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>

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)?

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

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

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")

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") is telling you that t() is a (S3) generic function that has methods for different object classes.

The S3 method dispatch system

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

"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>

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.

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 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") )

It will not suffice to supply the partial signature

getMethod("extract",signature="SpatialPolygons")
#Error in getMethod("extract", signature = "SpatialPolygons") : 
#  No method found for function "extract" and signature SpatialPolygons

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>

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.

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.

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.

Compiled code in a package

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")

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])

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.

Compiled code in a base package

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.

Compiled code built into the R interpreter

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'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天全站免登陆