如何查看R .Internal或.Primitive函数的源代码?


80

这些都没有显示pnorm功能的源代码,

stats:::pnorm
getAnywhere(pnorm)  

我如何查看的源代码pnorm

sum
 (..., na.rm = FALSE)  .Primitive("sum")
.Primitive("sum")
function (..., na.rm = FALSE)  .Primitive("sum")
methods(sum)
no methods were found

而且,如何查看该sum函数的源代码?

Answers:


95

的R源代码pnorm为:

function (q, mean = 0, sd = 1, lower.tail = TRUE, log.p = FALSE) 
.Call(C_pnorm, q, mean, sd, lower.tail, log.p)

因此,从技术上来讲,键入“ pnorm”确实会向您显示源代码。但是,更有用的pnorm是:的胆量是用C编码的,因此R中以前的问题视图源代码中的建议仅对外围有用(大部分集中于隐藏在名称空间中的函数等)。

Uwe Ligges在R news(p。43)中的文章是很好的一般参考。从该文档中:

查看R源代码时,有时会出现对以下函数之一的调用:.C()、. Call()、. Fortran()、. External()或.Internal()和.Primitive()。这些函数在诸如共享对象,静态库或动态链接库之类的已编译代码中调用入口点。因此,如果需要完全了解代码,则有必要查看编译后的代码的来源。...第一步是如果调用R函数是.Primitive()或.Internal(),则在文件$ R HOME / src / main / names.c中查找入口点。在下面的示例中,这是针对实现“简单” R函数sum()的代码完成的。

(添加了重点,因为您询问(sum)的精确函数已在Ligges的文章中介绍。)

根据您对代码的重视程度,可能有必要按照Ligges的建议下载和解压缩源代码(例如,然后可以使用命令行工具grep搜索源代码)。要进行更随意的检查,您可以通过R Subversion服务器Winston Chang的github镜像在线查看源(此处的链接专门指向src/nmath/pnorm.c)。(在正确的位置找到了,src/nmath/pnorm.c这使您对R源代码的结构有所了解。)

mean并且sum都在summary.c中实现。


1
与属于不同的类别pnorm。尝试mean.default使用R代码,并在github.com/wch/r-source/blob/trunk/src/main/summary.c中获得C代码。并阅读上面链接的Uwe Ligges的文章!
Ben Bolker

1
只是为了跟进这个答案:可能还需要注意C或Fortran中的确切函数名称。示例:我正在尝试查找的源stl,该源调用此行:z <- .Fortran(C_stl, x, n, as.integer(period), as.integer(s.window)。因此,我搜索了上面由关键字链接的Github镜像C_stl,但无济于事。但是,当我搜索时,stl有一个文件叫做stl.f我要查找的文件。关键是.c或.f文件名可能与所调用的函数名不完全相同。
yuqli

35

我知道这篇文章已有2年多的历史了,但是我认为这对某些浏览此问题的用户可能有用。

我基本上只是将我的答案复制到另一个类似的问题,以便对于某些想要探索C源文件的R用户来说可能很有用。

  1. 首先,使用pryr,您可以使用该show_c_source函数在GitHub上搜索C源文件中的相关代码。适用于.Internal和.Primitive函数。

    body(match.call)
    
    # .Internal(match.call(definition, call, expand.dots))
    
    pryr::show_c_source(.Internal(match.call(definition, call, expand.dots)))
    

    这将带您到此页面,显示其中unique.c包含函数do_matchcall

  2. 我将这个制表符分隔的文件放在一起,以该names.c文件为基础,并使用文件中的查找来确定源代码的位置。有一些功能具有特定于平台的文件,而其他一些功能则具有多个具有相关源代码的文件。但是对于其余部分,映射至少在当前版本(3.1.2)中已经很好地建立了。


当我尝试为以下代码查找C代码时,pryr不起作用systempryr::show_c_source(.Internal(system(x)))Error: Could not find entry for system
zhanxw

7
> methods(mean)
[1] mean.data.frame mean.Date       mean.default    mean.difftime   mean.IDate*    
[6] mean.POSIXct    mean.POSIXlt    mean.yearmon*   mean.yearqtr*  

   Non-visible functions are asterisked
> mean.default
function (x, trim = 0, na.rm = FALSE, ...) 
{
    if (!is.numeric(x) && !is.complex(x) && !is.logical(x)) {
        warning("argument is not numeric or logical: returning NA")
        return(NA_real_)
    }
    if (na.rm) 
        x <- x[!is.na(x)]
    if (!is.numeric(trim) || length(trim) != 1L) 
        stop("'trim' must be numeric of length one")
    n <- length(x)
    if (trim > 0 && n) {
        if (is.complex(x)) 
            stop("trimmed means are not defined for complex data")
        if (any(is.na(x))) 
            return(NA_real_)
        if (trim >= 0.5) 
            return(stats::median(x, na.rm = FALSE))
        lo <- floor(n * trim) + 1
        hi <- n + 1 - lo
        x <- sort.int(x, partial = unique(c(lo, hi)))[lo:hi]
    }
    .Internal(mean(x))
}
<bytecode: 0x155ef58>
<environment: namespace:base>

这似乎并不能回答OP的原始问题(关于pnorm),而是在下面关于他们的评论mean-并请注意,这也属于C代码的底部(请参阅下面的评论)。
Ben Bolker

2
确实。而“正确答案”就是您先前给出的答案……请阅读RNews中的Uwe Ligges的文章。
IRTFM
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.