2016-03-02 3 views
1

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

Во-первых, мы создали среду

env <- new.env() 

Один способ, которым я мог бы сделать это, получив вызов и изменить его. Однако я не знаю, как это сделать с помощью примитивной функции.

## Option 1: get the call and modify it 
env$`[` <- function(x, i, j, ...) { 
    my.call <- match.call() 
    ## This isn't allowed. 
    my.call[[1]] <- as.name(.Primitive("[")) 

    record.some.things.about(i, j) 

    eval(my.call, envir = parent.frame()) 
} 

В качестве альтернативы, я мог бы просто получить аргументы и использовать do.call. Однако я не разработал, как правильно извлекать аргументы.

## Option 2: do a call with the arguments 
env$`[` <- function(x, i, j, ...) { 
    ## This outputs a list, so if 'i' is missing, then 'j' ends up in the 'i' position. 
    ## If I could get an alist here instead, I could keep 'j' in the right position. 
    my.args <- match.call()[-1] 

    record.some.things.about(i, j) 

    do.call(
     .Primitive("["), 
     my.args, 
     envir = parent.frame() 
    ) 
} 

Тогда, если мы сделали все правильно, мы можем Eval некоторого выражения, которое использует [ внутри среде мы построили, и наша инструментальная функция будет вызываться вместо:

## Should return data.frame(b = c(4, 5, 6)) 
evalq(
    data.frame(a = c(1, 2, 3), b = c(4, 5, 6))[, "b"], 
    envir = env 
) 

Может кто-нибудь помогает/советует?

+1

Возможно отношение: http://stackoverflow.com/questions/23124096/r-decorator-to-change-both-input-and-output – nrussell

+0

То, что я, как правило, сделать, чтобы исправить некоторые значения по умолчанию - это что-то в следующих строках: Скажем, я хочу, чтобы 'table' всегда включал отсутствующие значения, а затем в начале моего скрипта я использовал таблицу <- function (x, ...) base :: : table (x, ..., useNA = "ifany") '. Независимо от того, что вы хотите записать о 'i' и' j', вы, вероятно, могли бы построить что-то подобное. – coffeinjunky

+1

Можете ли вы более подробно объяснить, чего хотите достичь? Если я правильно понимаю, вы либо хотите написать метод для '[' или хотите заменить '[' своей собственной функцией. Однако имя вашей функции меня сбивает с толку. – Roland

ответ

4

Использование trace:

trace(`[.data.frame`, quote({print("hello!")}), at = 1) 
iris[1,] 
#Tracing `[.data.frame`(iris, 1,) step 1 
#[1] "hello!" 
# Sepal.Length Sepal.Width Petal.Length Petal.Width Species 
#1   5.1   3.5   1.4   0.2 setosa 
+0

А, намного проще ... – GlennS

0

Не можете ли вы просто захватить все для оригинальных аргументов функций с тройными точками arg, которые передаются исходной функции?

sum <- function(..., na.rm = TRUE) { 
    print("my sum") # here is where you can "record some info" 
    base::sum(..., na.rm = na.rm) # then call original function w/ ... 
} 

base::sum(5,5, NA) 
##[1] NA 

# your function 
sum(5,5, NA) 
##[1] "my sum" 
##[1] 10 
Смежные вопросы