Как посмотреть исходный код функции R.Internal или .Primitive?

81

Ни один из них не показывает исходный код 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функции?

Bqsj Sjbq
источник

Ответы:

96

Исходный код 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 полезны лишь периферийно (большая часть из них сосредоточена на функциях, скрытых в пространствах имен и т. Д.).

Статья Уве Лиггеса в R news (стр. 43) является хорошей общей ссылкой. Из этого документа:

При просмотре исходного кода R иногда появляются вызовы одной из следующих функций: .C (), .Call (), .Fortran (), .External () или .Internal () и .Primitive (). Эти функции вызывают точки входа в скомпилированном коде, таком как общие объекты, статические библиотеки или библиотеки динамической компоновки. Поэтому необходимо заглянуть в источники скомпилированного кода, если требуется полное понимание кода. ... Первый шаг - найти точку входа в файле '$ R HOME / src / main / names.c', если вызывающая функция R либо .Primitive (), либо .Internal (). Это делается в следующем примере кода, реализующего «простую» функцию R sum ().

(Акцент добавлен, потому что точная функция, о которой вы спрашивали ( sum), описана в статье Лиггеса.)

В зависимости от того, насколько серьезно вы хотите вникнуть в код, возможно, стоит загрузить и распаковать исходный код, как предлагает Ligges (например, тогда вы можете использовать инструменты командной строки, такие как grepпоиск в исходном коде). Для более случайной проверки вы можете просмотреть источники в Интернете через сервер R Subversion или зеркало 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. И обязательно прочтите статью Уве Лиггеса по ссылке выше!
Бен Болкер,
1
Просто чтобы продолжить этот ответ: возможно, нужно быть осторожным с точным именем функции в C или Fortran. Пример: я пытался посмотреть на источник stl, который вызывает эту строку: z <- .Fortran(C_stl, x, n, as.integer(period), as.integer(s.window). Поэтому я C_stlбезрезультатно искал зеркало Github, указанное выше по ключевому слову . Однако, когда я ищу, stlесть файл с именем, stl.fкоторый я хочу найти. Вывод: имя файла .c или .f может не совпадать с именем вызываемой функции.
yuqli
35

Я знаю, что этому посту больше двух лет, но я подумал, что это может быть полезно для некоторых пользователей, просматривающих этот вопрос.

Я просто копирую свой ответ на этот другой похожий вопрос, чтобы он мог оказаться полезным для некоторых пользователей R, которые хотят изучить исходные файлы C.

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

Доминик Комтуа
источник
pryr не работает, когда я пытался найти коды C для system:, pryr::show_c_source(.Internal(system(x)))я получилError: Could not find entry for system
zhanxw 03
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>
IRTFM
источник
Кажется, это не отвечает на исходный вопрос OP (о pnorm), но их комментарий ниже mean- и обратите внимание, что это также попадает в код C внизу (см. Мой комментарий ниже).
Бен Болкер,
2
Конечно. И «правильный ответ» - это тот, который вы дали ранее ... прочтите статью Уве Лиггеса в RNews.
IRTFM