Jak wyświetlić kod źródłowy funkcji R .Internal lub .Primitive?


81

Żaden z nich nie pokazuje kodu źródłowego pnormfunkcji,

stats:::pnorm
getAnywhere(pnorm)  

Jak mogę zobaczyć kod źródłowy programu pnorm?

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

i jak mogę zobaczyć kod źródłowy sumfunkcji?

Odpowiedzi:


96

Kod źródłowy R programu pnormto:

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

Tak, technicznie rzecz biorąc, wpisując „pnorm” ma pokazać kod źródłowy. Jednak bardziej użyteczne: wnętrzności pnormsą kodowane w C, więc rada z poprzedniego pytania, aby zobaczyć kod źródłowy w R, jest przydatna tylko peryferyjnie (większość z nich koncentruje się na funkcjach ukrytych w przestrzeniach nazw itp.).

Artykuł Uwe Liggesa w R news (s. 43) jest dobrym odniesieniem ogólnym. Z tego dokumentu:

Podczas przeglądania kodu źródłowego R czasami pojawiają się wywołania jednej z następujących funkcji: .C (), .Call (), .Fortran (), .External () lub .Internal () i .Primitive (). Te funkcje wywołują punkty wejścia w skompilowanym kodzie, takim jak obiekty współużytkowane, biblioteki statyczne lub biblioteki dołączane dynamicznie. Dlatego konieczne jest zajrzenie do źródeł skompilowanego kodu, jeśli wymagane jest pełne zrozumienie kodu. ... Pierwszym krokiem jest wyszukanie punktu wejścia w pliku „$ R HOME / src / main / names.c”, jeśli wywołująca funkcję R to .Primitive () lub .Internal (). Odbywa się to w poniższym przykładzie dla kodu implementującego „prostą” funkcję R sum ().

(Podkreślenie dodane, ponieważ dokładna funkcja, o którą pytałeś ( sum), jest omówiona w artykule Ligges.)

W zależności od tego, jak poważnie chcesz zagłębić się w kod, warto pobrać i rozpakować kod źródłowy, jak sugeruje Ligges (na przykład możesz użyć narzędzi wiersza poleceń, takich jak grepprzeszukiwanie kodu źródłowego). Aby uzyskać bardziej swobodną inspekcję, możesz przeglądać źródła online za pośrednictwem serwera R Subversion lub serwera lustrzanego github Winston Chang (linki tutaj prowadzą do src/nmath/pnorm.c). (Odgadnięcie właściwego miejsca src/nmath/pnorm.c, wymaga pewnej znajomości struktury kodu źródłowego R.)

meani sumoba są zaimplementowane w Summary . c.


1
jest w innej kategorii niż pnorm. Spróbuj znaleźć mean.defaultkod R, a github.com/wch/r-source/blob/trunk/src/main/summary.c kod C. I przeczytaj artykuł Uwe Ligges, do którego link znajduje się powyżej!
Ben Bolker

1
Aby kontynuować tę odpowiedź: być może trzeba będzie uważać na dokładną nazwę funkcji w języku C lub Fortran. Przykład: Starałem się spojrzeć na źródło stl, które wywołuje ten wiersz: z <- .Fortran(C_stl, x, n, as.integer(period), as.integer(s.window). Więc C_stlbezskutecznie przeszukałem serwer lustrzany Github powiązany powyżej za pomocą słowa kluczowego . Jednak podczas wyszukiwania stljest plik o nazwie, stl.fktóry chcę znaleźć. Na wynos jest nazwa pliku .c lub .f, która może nie być dokładnie taka sama jak nazwa funkcji, która jest wywoływana.
yuqli

35

Wiem, że ten post ma więcej niż 2 lata, ale pomyślałem, że może to być przydatne dla niektórych użytkowników przeglądających to pytanie.

Po prostu kopiuję swoją odpowiedź na to inne podobne pytanie, aby mogło się przydać niektórym użytkownikom języka R, którzy chcą eksplorować pliki źródłowe C.

  1. Po pierwsze, z pryr możesz użyć show_c_sourcefunkcji, która wyszuka na GitHubie odpowiedni fragment kodu w plikach źródłowych C. Działa dla funkcji .Internal i .Primitive.

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

    Co prowadzi do tej strony , pokazując, że unique.czawiera funkcję do_matchcall .

  2. Utworzyłem ten plik rozdzielany tabulatorami , opierając się na names.cpliku i używając funkcji znajdowania plików do określenia lokalizacji kodu źródłowego. Niektóre funkcje mają pliki specyficzne dla platformy i kilka innych, dla których istnieje więcej niż jeden plik z odpowiednim kodem źródłowym. Ale w pozostałej części mapowanie jest dość dobrze ugruntowane, przynajmniej dla aktualnej wersji (3.1.2).


pryr nie działa, gdy próbowałem odnaleźć kody dla C system: pryr::show_c_source(.Internal(system(x))), mamError: 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>

Wydaje się, że nie odpowiada to pierwotnemu pytaniu OP (o pnorm), ale ich komentarz poniżej mean- i zauważ, że dotyczy to również kodu C, na dole (zobacz mój komentarz poniżej).
Ben Bolker

2
W rzeczy samej. A „prawidłowa odpowiedź” to ta, którą podałeś wcześniej… przeczytaj artykuł Uwe Ligges w RNews.
IRTFM,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.