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

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

> t
function (x) 
UseMethod("t")
<bytecode: 0x2332948>
<environment: namespace:base>

в этом случае, что делает UseMethod("t") в смысле? Как найти исходный код, который фактически используется, например:t(1:10)?

есть ли разница между тем, когда я вижу UseMethod и когда я вижу standardGeneric и showMethods, а с 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.

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

> 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

как найти такие функции, как .cbindts и .makeNamesTs?

в других случаях есть немного кода R, но большая часть работы, похоже, выполняется где-то еще.

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

как я узнаю, что

9 ответов


UseMethod("t") говорит, что t() в (S3) универсальная функция, которая имеет методы для разных классов объектов.

система отправки метода S3

для классов S3 вы можете использовать methods функция для перечисления методов для конкретной универсальной функции или класса.

> methods(t)
[1] t.data.frame t.default    t.ts*       

   Non-visible functions are asterisked
> methods(class="ts")
 [1] aggregate.ts     as.data.frame.ts cbind.ts*        cycle.ts*       
 [5] diffinv.ts*      diff.ts          kernapply.ts*    lines.ts        
 [9] monthplot.ts*    na.omit.ts*      Ops.ts*          plot.ts         
[13] print.ts         time.ts*         [<-.ts*          [.ts*           
[17] t.ts*            window<-.ts*     window.ts*      

   Non-visible functions are asterisked

"невидимые функции помечены звездочкой"означает, что функция не экспортируется из пространства имен пакета. Вы все еще можете просмотреть его исходный код через the


В дополнение к другим ответам на этот вопрос и его дубликатам, вот хороший способ получить исходный код для функции пакета без необходимости знать, в каком пакете он находится. например, если нам нужен источник для randomForest::rfcv():

до просмотр/редактирование в открывшемся окне:

edit(getAnywhere('rfcv'), file='source_rfcv.r')

до редирект в отдельный файл:

capture.output(getAnywhere('rfcv'), file='source_rfcv.r')

он раскрывается при отладке с помощью функции debug (). Предположим,вы хотите увидеть базовый код в функции t () transpose. Просто набрав "t", не раскрывает многого.

>t 
function (x) 
UseMethod("t")
<bytecode: 0x000000003085c010>
<environment: namespace:base>

но, используя " debug (functionName)", он показывает базовый код, без внутренних элементов.

> debug(t)
> t(co2)
debugging in: t(co2)
debug: UseMethod("t")
Browse[2]> 
debugging in: t.ts(co2)
debug: {
    cl <- oldClass(x)
    other <- !(cl %in% c("ts", "mts"))
    class(x) <- if (any(other)) 
        cl[other]
    attr(x, "tsp") <- NULL
    t(x)
}
Browse[3]> 
debug: cl <- oldClass(x)
Browse[3]> 
debug: other <- !(cl %in% c("ts", "mts"))
Browse[3]> 
debug: class(x) <- if (any(other)) cl[other]
Browse[3]>  
debug: attr(x, "tsp") <- NULL
Browse[3]> 
debug: t(x)

EDIT: debugonce () выполняет то же самое без использования undebug ()


не видел, как это вписывается в поток основного ответа, но он поставил меня в тупик на некоторое время, поэтому я добавляю его здесь:

Операторы Infix

чтобы увидеть исходный код некоторых базовых операторов infix (например, %%, %*%, %in%), используйте getAnywhere, например:

getAnywhere("%%")
# A single object matching ‘%%’ was found
# It was found in the following places
#   package:base
#   namespace:base
#  with value
#
# function (e1, e2)  .Primitive("%%")

основной ответ охватывает, как затем использовать зеркала, чтобы копать глубже.


для непримитивных функций R base включает функцию body() Это возвращает тело функции. Например, источник print.Date() функция может быть просмотрена:

body(print.Date)

будет:

{
    if (is.null(max)) 
        max <- getOption("max.print", 9999L)
    if (max < length(x)) {
        print(format(x[seq_len(max)]), max = max, ...)
        cat(" [ reached getOption(\"max.print\") -- omitted", 
            length(x) - max, "entries ]\n")
    }
    else print(format(x), max = max, ...)
    invisible(x)
}

если вы работаете в скрипте и хотите код функции в качестве вектора символов, вы можете его получить.

capture.output(print(body(print.Date)))

вы получите:

[1] "{"                                                                   
[2] "    if (is.null(max)) "                                              
[3] "        max <- getOption(\"max.print\", 9999L)"                      
[4] "    if (max < length(x)) {"                                          
[5] "        print(format(x[seq_len(max)]), max = max, ...)"              
[6] "        cat(\" [ reached getOption(\\"max.print\\") -- omitted\", "
[7] "            length(x) - max, \"entries ]\n\")"                      
[8] "    }"                                                               
[9] "    else print(format(x), max = max, ...)"                           
[10] "    invisible(x)"                                                    
[11] "}"     

зачем мне это делать? Я создавал пользовательский S3 объект (x, где class(x) = "foo") на основании списка. Один из членов списка (с именем "fun") был функцией, и я хотел print.foo() чтобы отобразить исходный код функции, отступ. Поэтому я закончил со следующим фрагментом в print.foo():

sourceVector = capture.output(print(body(x[["fun"]])))
cat(paste0("      ", sourceVector, "\n"))

какие отступы и отображает код, связанный с x[["fun"]].


есть очень удобная функция в R edit

new_optim <- edit(optim)

он откроет исходный код optim используя редактор, указанный в R options, а затем вы можете отредактировать его и назначить измененную функцию new_optim. Мне очень нравится эта функция для просмотра кода или отладки кода, e.g, распечатайте некоторые сообщения или переменные или даже назначьте их глобальным переменным для дальнейшего исследования (конечно, вы можете использовать debug).

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

invisible(edit(optim))

очевидно, что это не может использоваться для просмотра исходного кода C/C++ или Fortran.

кстати, edit может открывать другие объекты, такие как список, матрица и т. д., которые затем показывают структуру данных с атрибутами. Функция de можно использовать для открытия редактора excel like (если GUI поддерживает его), чтобы изменить матрицу или фрейм данных и вернуть новый. Это удобно иногда, но должно быть избегайте в обычном случае, особенно когда вы матрица большая.


пока функция написана на чистом R не C / C++ / Fortran, можно использовать следующее. В противном случае лучший способ -отладка и с помощью "прыжок на":

> functionBody(functionName)

View([function_name]) - ЭГ. View(mean) обязательно используйте верхний регистр [V]. В Редакторе откроется код только для чтения.


вы также можете попробовать использовать print.function(), который является общим S3, чтобы получить функцию write в консоли.