我想看看源代码的功能,看看它是如何工作的。 我知道我可以在提示符下输入其名称打印功能:
> 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
。 我如何才能找到这些源代码?
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
可以,因为它会直接带您到一个页面GitHub的一个有用的工具.Internal
和.Primitive
电话。 包可以使用.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:::C_optimhess
看到有关的编译函数被调用的信息。
在一个包已编译代码
如果你想在一个包来查看编译的代码,你需要下载/解压缩包源。 安装的二进制文件是不够的。 一个包的源代码可以从相同的CRAN(或CRAN兼容),该软件包最初是从安装库。 该download.packages()
函数可以得到包源为您服务。
download.packages(pkgs = "Matrix",
destdir = ".",
type = "source")
这将下载矩阵包的源版本,并保存相应.tar.gz
文件在当前目录中。 对编译函数的源代码可以在发现src
未压缩和untared文件的目录。 的解压缩和untaring步骤可以的外部进行R
,或从内R
使用untar()
函数。 它可以下载和膨胀处理成一个单一的呼叫合并(注意,只有一个包在同一时间可以以这种方式被下载并解压):
untar(download.packages(pkgs = "Matrix",
destdir = ".",
type = "source")[,2])
或者,如果软件包开发是公开托管(例如,通过GitHub上 , R-伪造 ,或RForge.net ),你也许可以在线浏览源代码。
在碱包编译代码
某些包被认为是“基地”的包。 这些封装运送用R和它们的版本被锁定到R.实施例的版本包括base
, compiler
, stats
,和utils
。 因此,它们不能用作在CRAN如上所述单独的可下载的软件包。 相反,它们是在根据单个包装体目录将R源树的一部分/src/library/
。 如何访问将R源将在下一节中描述。
内置转换为R解释编译代码
如果您要查看内置到R解释的代码,你需要下载/解压将R来源; 或者您也可以通过R在线查看源代码Subversion版本库或温斯顿畅的github上镜 。
乌韦Ligges的ř新闻文章(PDF) (第43页)是如何查看源代码中的良好的一般参考.Internal
和.Primitive
功能。 基本步骤是先寻找在函数名src/main/names.c
,然后搜索“C-条目”的名字在文件中src/main/*
。
除了对这个问题和它的重复其他的答案,这里是得到一个包功能的源代码,而不必知道它是在哪个包的好方法例如,如果我们想为源。 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>
但是,使用“调试(functionName)”,它揭示了底层代码,SAN的内部。
> 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()
对于非原始功能,R基包括功能称为body()
返回的函数的体。 例如,所述的源极print.Date()
函数可以被看作:
body(print.Date)
会产生这样的:
{
if (is.null(max))
max <- getOption("max.print", 9999L)
if (max < length(x)) {
print(format(x[seq_len(max)]), max = max, ...)
cat(" [ reached getOption(\"max.print\") -- omitted",
length(x) - max, "entries ]\n")
}
else print(format(x), max = max, ...)
invisible(x)
}
如果您在脚本的工作,并希望该功能码为一个特征向量,就可以得到它。
capture.output(print(body(print.Date)))
将让你:
[1] "{"
[2] " if (is.null(max)) "
[3] " max <- getOption(\"max.print\", 9999L)"
[4] " if (max < length(x)) {"
[5] " print(format(x[seq_len(max)]), max = max, ...)"
[6] " cat(\" [ reached getOption(\\\"max.print\\\") -- omitted\", "
[7] " length(x) - max, \"entries ]\\n\")"
[8] " }"
[9] " else print(format(x), max = max, ...)"
[10] " invisible(x)"
[11] "}"
为什么我会想要做这样的事情? 我被创建自定义S3对象( x
,其中, class(x) = "foo"
基于列表上)。 一个列表的成员(命名为“好玩”)是一个功能,我想print.foo()
显示功能的源代码,缩进。 所以我结束了下面的代码片段print.foo()
sourceVector = capture.output(print(body(x[["fun"]])))
cat(paste0(" ", sourceVector, "\n"))
其缩进和显示与相关联的代码x[["fun"]]
没有看到这如何适应主要答复的流量,但它难倒我了一段时间,所以我在这里将它:
中缀运算符
看到一些碱中缀运算符(例如,源代码%%
, %*%
%in%
),使用getAnywhere
,例如:
getAnywhere("%%")
# A single object matching ‘%%’ was found
# It was found in the following places
# package:base
# namespace:base
# with value
#
# function (e1, e2) .Primitive("%%")
主要的答案包括如何再使用镜子进行深入分析。
有R中一个非常方便的功能edit
new_optim <- edit(optim)
这将打开的源代码optim
使用R中的规定的编辑options
,然后就可以编辑和分配修正功能new_optim
。 我很喜欢这个功能非常多,查看代码或调试代码,例如,打印一些信息或变量,甚至将其分配给作进一步调查一个全局变量(当然你也可以使用debug
)。
如果你只是想查看源代码,不希望打印您的控制台上恼人的长源代码,你可以使用
invisible(edit(optim))
显然,这不能用于查看C / C ++或Fortran源代码。
顺便说一句, edit
可以打开其他对象像列表,矩阵,等,然后示出了具有属性的数据结构为好。 功能de
可用于打开一个Excel等编辑(如果GUI支持的话)来修改矩阵或数据帧,并返回新的。 这是非常方便的时候,但是应该通常情况下是可以避免的,尤其是当你矩阵大。
只要功能是写在纯的R不是C / C ++ / Fortran的,可以使用以下内容。 否则,最好的办法就是调试和使用“ 跳入 ”:
> functionBody(functionName)
View([function_name])
-如。 View(mean)
请务必使用大写[V]。 只读代码将在编辑器中打开。
您也可以尝试使用print.function()
这是S3通用,获得在控制台的功能写。
在RStudio,有(至少)3种方式:
- 按F2键,光标在任何函数。
- 点击函数名,同时按住Ctrl或Command
-
View
(执行)(如上所述)
一个新的面板将源代码开放。 如果达到.Primitive或.C你需要另一种方法,对不起。