Come vedere il codice sorgente di R. Funzione interna o .Primitive?

Nessuno dei due mostra il codice sorgente della funzione pnorm ,

 stats:::pnorm getAnywhere(pnorm) 

Come posso vedere il codice sorgente di pnorm ?

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

e, come posso vedere il codice sorgente della funzione sum ?

Il codice sorgente R di pnorm è:

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

Quindi, tecnicamente parlando, digitando “pnorm” ti mostra il codice sorgente. Tuttavia, più efficacemente: le viscere di pnorm sono codificate in C, quindi il consiglio nella domanda precedente visualizza il codice sorgente in R è solo marginalmente utile (la maggior parte si concentra su funzioni nascoste in spazi dei nomi ecc.).

L’ articolo di Uwe Ligges in R news (pagina 43) è un buon riferimento generale. Da quel documento:

Quando si guarda il codice sorgente R, a volte vengono chiamate a una delle seguenti funzioni: .C (), .Call (), .Fortran (), .External () o .Internal () e .Primitive (). Queste funzioni chiamano i punti di ingresso nel codice compilato come oggetti condivisi, librerie statiche o librerie di collegamenti dinamici. Pertanto, è necessario esaminare le fonti del codice compilato, se è richiesta la completa comprensione del codice. … Il primo passo è cercare il punto di ingresso nel file ‘$ R HOME / src / main / names.c’, se la funzione R chiamante è .Primitive () o .Internal (). Questo viene fatto nel seguente esempio per il codice che implementa la funzione R semplice ().

(Enfasi aggiunta perché l’esatta funzione che hai chiesto ( sum ) è trattata nell’articolo di Ligges.)

A seconda di quanto seriamente si voglia scavare nel codice, potrebbe essere utile scaricare e decomprimere il codice sorgente come suggerisce Ligges (ad esempio, è ansible utilizzare strumenti da riga di comando come grep per cercare attraverso il codice sorgente). Per ulteriori ispezioni casuali, è ansible visualizzare le fonti online tramite il server R Subversion o il mirror github di Winston Chang (i collegamenti qui sono specifici per src/nmath/pnorm.c ). (Indovinare il posto giusto per guardare, src/nmath/pnorm.c , richiede una certa familiarità con la struttura del codice sorgente R.)

mean e sum sono entrambi implementati in summary.c .

So che questo post ha più di 2 anni, ma ho pensato che questo potesse essere utile ad alcuni utenti che navigano attraverso questa domanda.

Fondamentalmente sto semplicemente copiando la mia risposta a questa altra domanda simile in modo che possa rivelarsi utile per alcuni utenti R che desiderano esplorare i file sorgente C.

  1. Innanzitutto, con pryr puoi usare la funzione show_c_source che cercherà su GitHub la parte di codice rilevante nei file di origine C. Funziona per. Funzioni interne e .Primitive.

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

    Che ti porta a questa pagina , mostrando che unique.c contiene la funzione do_matchcall .

  2. Ho messo insieme questo file delimitato da tabulazioni , basandosi sul file names.c e utilizzando find-in-files per determinare la posizione del codice sorgente. Esistono alcune funzioni con file specifici della piattaforma e una manciata di altre per le quali esiste più di un file con codice sorgente pertinente. Ma per il resto la mapping è abbastanza consolidata, almeno per la versione attuale (3.1.2).

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