Eu quero olhar para o código fonte de uma função para ver como ele funciona. Sei que posso imprimir uma função digitando seu nome no prompt:
> t
function (x)
UseMethod("t")
<bytecode: 0x2332948>
<environment: namespace:base>
Nesse caso, o que UseMethod("t")
significa? Como localizo o código fonte que realmente está sendo usado, por exemplo t(1:10)
:?
Existe uma diferença entre quando eu vejo UseMethod
e quando eu vejo standardGeneric
e showMethods
, como acontece com with
?
> with
standardGeneric for "with" defined from package "base"
function (data, expr, ...)
standardGeneric("with")
<bytecode: 0x102fb3fc0>
<environment: 0x102fab988>
Methods may be defined for arguments: data
Use showMethods("with") for currently available ones.
Em outros casos, posso ver que as funções R estão sendo chamadas, mas não consigo encontrar o código-fonte para essas funções.
> ts.union
function (..., dframe = FALSE)
.cbind.ts(list(...), .makeNamesTs(...), dframe = dframe, union = TRUE)
<bytecode: 0x36fbf88>
<environment: namespace:stats>
> .cbindts
Error: object '.cbindts' not found
> .makeNamesTs
Error: object '.makeNamesTs' not found
Como encontro funções como .cbindts
e .makeNamesTs
?
Em outros casos, ainda há um pouco de código R, mas a maior parte do trabalho parece ser feita em outro lugar.
> matrix
function (data = NA, nrow = 1, ncol = 1, byrow = FALSE, dimnames = NULL)
{
if (is.object(data) || !is.atomic(data))
data <- as.vector(data)
.Internal(matrix(data, nrow, ncol, byrow, dimnames, missing(nrow),
missing(ncol)))
}
<bytecode: 0x134bd10>
<environment: namespace:base>
> .Internal
function (call) .Primitive(".Internal")
> .Primitive
function (name) .Primitive(".Primitive")
Como descubro o que a .Primitive
função faz? Da mesma forma, algumas funções chamar .C
, .Call
, .Fortran
, .External
, ou .Internal
. Como posso encontrar o código fonte para esses?
Respostas:
UseMethod("t")
está dizendo quet()
é uma função genérica ( S3 ) que possui métodos para diferentes classes de objetos.O sistema de despacho do método S3
Para classes S3, você pode usar a
methods
função para listar os métodos para uma função ou classe genérica específica."Funções não visíveis estão com asterisco" significa que a função não é exportada do espaço para nome do pacote. Você ainda pode visualizar seu código fonte através da
:::
função (ou sejastats:::t.ts
) ou usandogetAnywhere()
.getAnywhere()
é útil porque você não precisa saber de qual pacote a função veio.O sistema de despacho do método S4
O sistema S4 é um sistema de despacho de método mais recente e é uma alternativa ao sistema S3. Aqui está um exemplo de uma função S4:
A saída já oferece muita informação.
standardGeneric
é um indicador de uma função S4. O método para ver os métodos S4 definidos é oferecido de maneira útil:getMethod
pode ser usado para ver o código fonte de um dos métodos:Também existem métodos com assinaturas mais complexas para cada método, por exemplo
Para ver o código fonte de um desses métodos, toda a assinatura deve ser fornecida, por exemplo
Não será suficiente fornecer a assinatura parcial
Funções que chamam funções não exportadas
No caso de
ts.union
,.cbindts
e.makeNamesTs
são funções não exportadas dostats
espaço para nome. Você pode visualizar o código fonte de funções não exportadas usando o:::
operador ougetAnywhere
.Funções que chamam código compilado
Observe que "compilado" não se refere ao código R compilado em bytes, criado pelo pacote do compilador . A
<bytecode: 0x294e410>
linha na saída acima indica que a função é compilada em bytes e você ainda pode visualizar a fonte na linha de comando R.Funções que chamada
.C
,.Call
,.Fortran
,.External
,.Internal
, ou.Primitive
estão chamando pontos de entrada no código compilado, assim que você tem que olhar para as fontes do código compilado, se você quiser entender completamente a função. Esse espelho do código-fonte do GitHub é um lugar decente para começar. A funçãopryr::show_c_source
pode ser uma ferramenta útil, pois o levará diretamente a uma página do GitHub para chamadas.Internal
e.Primitive
chamadas. Os pacotes podem usar.C
,.Call
,.Fortran
, e.External
; mas não.Internal
ou.Primitive
, porque são usados para chamar funções incorporadas ao intérprete R.Chamadas para algumas das funções acima podem usar um objeto em vez de uma cadeia de caracteres para fazer referência à função compilada. Nesses casos, o objectivo é de classe
"NativeSymbolInfo"
,"RegisteredNativeSymbol"
, ou"NativeSymbol"
; e imprimir o objeto produz informações úteis. Por exemplo,optim
chamadas.External2(C_optimhess, res$par, fn1, gr1, con)
(observe queC_optimhess
não"C_optimhess"
).optim
está no pacote de estatísticas, então você pode digitarstats:::C_optimhess
para ver informações sobre a função compilada que está sendo chamada.Código compilado em um pacote
Se você deseja visualizar o código compilado em um pacote, será necessário baixar / descompactar a fonte do pacote. Os binários instalados não são suficientes. O código-fonte de um pacote está disponível no mesmo repositório CRAN (ou compatível com CRAN) do qual o pacote foi originalmente instalado. A
download.packages()
função pode obter a fonte do pacote para você.Isso fará o download da versão de origem do pacote Matrix e salvará o
.tar.gz
arquivo correspondente no diretório atual. O código-fonte para funções compiladas pode ser encontrado nosrc
diretório do arquivo descompactado e não-marcado. A etapa de descompactação e descompactação pode ser feita foraR
ou a partir do interiorR
usando auntar()
função É possível combinar a etapa de download e expansão em uma única chamada (observe que apenas um pacote de cada vez pode ser baixado e descompactado desta maneira):Como alternativa, se o desenvolvimento do pacote for hospedado publicamente (por exemplo, via GitHub , R-Forge ou RForge.net ), você provavelmente poderá procurar o código-fonte on-line.
Código compilado em um pacote base
Certos pacotes são considerados pacotes "base". Estes pacotes fornecidos com R e sua versão é bloqueado para a versão de R. Exemplos incluem
base
,compiler
,stats
, eutils
. Como tal, eles não estão disponíveis como pacotes para download separados no CRAN, conforme descrito acima. Em vez disso, eles fazem parte da árvore de origem R em diretórios de pacotes individuais em/src/library/
. Como acessar a fonte R é descrito na próxima seção.Código compilado incorporado ao intérprete R
Se você deseja visualizar o código incorporado ao intérprete R, será necessário baixar / descompactar as fontes R; ou você pode visualizar as fontes on-line através do repositório R Subversion ou do espelho do github de Winston Chang .
O artigo de notícias R de Uwe Ligges (PDF) (p. 43) é uma boa referência geral de como visualizar o código fonte
.Internal
e as.Primitive
funções. As etapas básicas são primeiro procurar o nome da funçãosrc/main/names.c
e, em seguida, procurar o nome "C-entry" nos arquivossrc/main/*
.fonte
RStudio
, ele tentará puxar a fonte para a função em que o cursor de texto acabou, se você pressionar aF2
tecla.scale
que é S3 - eu obtiveUseMethod("scale")
e depois useigetAnywhere(scale.default)
). Mas funções simples funcionam muito bem.Além das outras respostas sobre esta questão e suas duplicatas, aqui está uma boa maneira de obter o código-fonte para uma função do pacote sem precisar saber em qual pacote ele está. Por exemplo, se queremos a fonte para
randomForest::rfcv()
:Para visualizar / editar em uma janela pop-up:
Para redirecionar para um arquivo separado :
fonte
View(foo)
; ondefoo
era uma função de um pacote já carregado.edit()
abre um editor de texto (à escolha do usuário) , enquantoView()
abre um visualizador de planilhas do tipo Excel para dados , o último é bom para navegar em dados (multi-colunares), mas geralmente péssimo para código que não seja o comprimento do brinquedo. Por exemplo, como eu sugiro, geralmente a primeira coisa que quero fazer ao procurar uma função é pular / recolher / manipular toda a lógica de análise de argumentos e ação padrão, para ver o que a função realmente faz .É revelado quando você depura usando a função debug (). Suponha que você queira ver o código subjacente na função de transposição t (). Apenas digitar 't', não revela muito.
Mas, usando o 'debug (functionName)', ele revela o código subjacente e sem os internos.
EDIT: debugonce () realiza o mesmo sem ter que usar undebug ()
fonte
debugonce
vez dedebug
neste caso.Para funções não primitivas, a base R inclui uma função chamada
body()
que retorna o corpo da função. Por exemplo, a fonte daprint.Date()
função pode ser visualizada:produzirá o seguinte:
Se você estiver trabalhando em um script e quiser o código de função como um vetor de caractere, poderá obtê-lo.
você receberá:
Por que eu iria querer fazer uma coisa dessas? Eu estava criando um objeto S3 personalizado (
x
, ondeclass(x) = "foo"
) com base em uma lista. Um dos membros da lista (chamado "divertido") era uma função e eu queriaprint.foo()
exibir o código fonte da função, recuado. Então, acabei com o seguinte trecho emprint.foo()
:que recua e exibe o código associado
x[["fun"]]
.fonte
Não vi como isso se encaixava no fluxo da resposta principal, mas me surpreendeu por um tempo, então estou adicionando aqui:
Operadores Infix
Para ver o código fonte de alguns operadores de base infixas (por exemplo,
%%
,%*%
,%in%
), o usogetAnywhere
, por exemplo:A resposta principal aborda como usar espelhos para ir mais fundo.
fonte
getAnywhere
. Ou você pode simplesmente usar backticks se você já sabe o nome do operador:`%in%`
.getAnywhere
também é mencionado na sua resposta, mas acho que uma referência específica ao infix é útil para referência futura a essa resposta - eu li essa página várias vezes e ainda estava um pouco perplexo tentando encontrar código para tais funções para um enquanto - e eu não achei que se encaixasse no fluxo de qualquer outra resposta (que ambos estão usandogetAnywhere
para outro propósito).Existe uma função muito útil em R
edit
Ele abrirá o código-fonte do
optim
uso do editor especificado em R'soptions
e, em seguida, você poderá editá-lo e atribuir a função modificadanew_optim
. Eu gosto muito dessa função para visualizar ou depurar o código, por exemplo, imprimir algumas mensagens ou variáveis ou até atribuí-las a variáveis globais para uma investigação mais aprofundada (é claro que você pode usardebug
).Se você deseja apenas visualizar o código-fonte e não deseja que o código-fonte longo e irritante seja impresso no seu console, você pode usar
Claramente, isso não pode ser usado para exibir o código-fonte C / C ++ ou Fortran.
BTW,
edit
pode abrir outros objetos como lista, matriz, etc., que também mostram a estrutura de dados com atributos. A funçãode
pode ser usada para abrir um editor como o Excel (se a GUI suportar) para modificar a matriz ou o quadro de dados e retornar o novo. Às vezes, isso é útil, mas deve ser evitado no caso usual, principalmente quando a matriz é grande.fonte
Desde que a função seja escrita em R puro e não em C / C ++ / Fortran, pode-se usar o seguinte. Caso contrário, a melhor maneira é depurar e usar " pular para ":
fonte
body
.identical(functionBody, body)
éTRUE
.base::body
emethods::functionBody
, embora seja improvável que sejam detidos.body
poderia ser substituído também: rdocumentation.org/search?q=bodyNo RStudio, existem (pelo menos) três maneiras:
View
(nome_da_função) (como indicado acima)Um novo painel será aberto com o código fonte. Se você acessar .Primitive ou .C, precisará de outro método, desculpe.
fonte
View([function_name])
- por exemplo.View(mean)
Certifique-se de usar maiúsculas [V]. O código somente leitura será aberto no editor.fonte
Você também pode tentar usar
print.function()
, que é o S3 genérico, para obter a função de gravação no console.fonte
print.function()
é um método S3 . O genérico éprint()
. E geralmente não é uma boa ideia chamar métodos diretamente. Isso anula todo o objetivo de funções genéricas e envio de métodos.