我想看看一个函数的源代码,看看它是如何工作的。我知道我可以通过在提示符处输入它的名称来打印一个函数:
> t
function (x)
UseMethod("t")
<bytecode: 0x2332948>
<environment: namespace:base>
在这种情况下,UseMethod(“t”)是什么意思?我如何找到实际正在使用的源代码,例如:t(1:10)?
当我看到UseMethod和当我看到standardGeneric和showMethods之间有区别吗?
> 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。我怎样才能找到它们的源代码?
对于非原语函数,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,其中类(x) = "foo")基于一个列表。列表成员之一(名为“fun”)是一个函数,我想打印.foo()显示缩进的函数源代码。所以我最终在print.foo()中得到了以下片段:
sourceVector = capture.output(print(body(x[["fun"]])))
cat(paste0(" ", sourceVector, "\n"))
它缩进并显示与x[["fun"]]相关的代码。
编辑2020-12-31
获得源代码相同字符向量的一种不那么迂回的方法是:
sourceVector = deparse(body(x$fun))
除了关于这个问题的其他答案及其副本之外,还有一种获得包函数源代码的好方法,而不需要知道它在哪个包中。
例如,如果我们想要randomForest::rfcv()的源代码:
在弹出窗口中查看/编辑:
edit(getAnywhere('rfcv'), file='source_rfcv.r')
View(getAnywhere('rfcv'), file='source_rfcv.r')
注意,edit()打开一个文本编辑器(由用户选择),而
View()调用电子表格样式的数据查看器。
View() is great for browsing (multi-columnar) data, but usually terrible for code of anything other than toy length.
so when only want to view code, edit() is IMO actually far better than View(), since with edit() you can collapse/hide/dummy out all the arg-parsing/checking/default/error-message logic which can take up to 70% of an R function, and just get to the part where the function actually operationally does something(!), what type(s) of objects its return type is, whether and how it recurses, etc.
重定向到一个单独的文件(这样你就可以在你最喜欢的IDE/编辑器/处理它的grep等):
capture.output(getAnywhere('rfcv'), file='source_rfcv.r')