Як побачити вихідний код функції 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функції?

Відповіді:


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

Залежно від того, наскільки серйозно ви хочете копатись у коді, можливо, варто завантажити та розпакувати вихідний код, як пропонує Ligges (наприклад, тоді ви можете використовувати інструменти командного рядка, такі як grepпошук у вихідному коді). Для більш випадкового огляду ви можете переглянути джерела в Інтернеті через сервер R Subversion або дзеркало github Вінстона Чанга (посилання тут стосуються конкретно src/nmath/pnorm.c). (Вгадавши правильне місце для пошуку, src/nmath/pnorm.cбере певне знайомство зі структурою вихідного коду R.)

meanі sumобидва вони реалізовані в резюме . c .


1
це в іншій категорії, ніж pnorm. Спробуйте mean.defaultкод R, а github.com/wch/r-source/blob/trunk/src/main/summary.c - код C. І прочитайте статтю Уве Ліггеса, зв’язану вище!
Ben Bolker

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

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

В основному я просто копіюю свою відповідь на це інше подібне запитання, щоб воно могло виявитися корисним для деяких користувачів 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

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- і зауважте, що це також потрапляє в код С, внизу (див. Мій коментар нижче).
Ben Bolker

2
Справді. І "правильна відповідь" - це та, яку ви дали раніше ... прочитайте статтю Уве Ліггеса в RNews.
IRTFM
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.