2014-07-10 47 views
9

Czy istnieje sposób uzyskiwania dostępu do zwracanej wartości funkcji, która jest śledzona przez funkcję określoną jako parametr wyjściowy do śledzenia? Brzmi to trudno, ale nie byłem w stanie uprościć pytania bez utraty informacji. Oto prosty przykład.Jak uzyskać dostęp do zwracanej wartości śledzonej funkcji?

Mamy prostą funkcję

add10 <- function(a){ 
    a + 10 
} 

a niektóre funkcje, które chcemy być wywołana, gdy wezwanie do Add10 wyjścia.

trace.exit() <- function(){ 
... 
} 

Śledzenie ustawia się w następujący sposób.

trace(add10, exit=trace.exit) 

I robimy wywołanie Add10

add10(5) 

Jak rozumiem od teraz, trace.exit będzie wywoływana po zakończeniu wykonywania add10. Czy jest jakiś sposób uzyskania dostępu do wartości zwracanej add10 wewnątrz trace.exit?

Czuję, że powinno być. Ale grając z sys.frames i przeglądając środowiska, nie byłem w stanie tego uzyskać.

Powodem tego jest chęć przechwycenia wszystkich wywołań funkcji i zwracanych wartości, które podają.

UPD Rozwiązanie z owijki lub coś podobnego jest ładny, ale trace już implementuje wzorzec dekorator, więc moje pytanie jest o dostępie do wartości zwracanej od trace, nie chodzi o rozwiązanie problemu dekoratorów w R.

+0

Trudno jest zobaczyć, gdzie ukryta jest wartość zwracana. W C wartości bliskie sobie nawzajem w [context.c] (https://github.com/wch/r-source/blob/fba3c1b0ac71bb5a681b2c1437ce2a38dfa3bb61/src/main/context.c#L197). Z tego, co mogę powiedzieć, 'jumpfun' ma ustawić wartość zwracaną na' val' w odpowiednim kontekście, ale wygląda na to, że funkcja 'on.exit' może działać w innym kontekście. Miałem nadzieję, że będzie dostępne w '.Last.value', ale wydaje się, że tak nie jest. Być może to interfejs użytkownika aktualizuje tę wartość. – MrFlick

Odpowiedz

4

Dlaczego czy nie użyć opakowania, które jednoznacznie przypisuje wartość zwracaną do zmiennej lokalnej:

add10 <- function(a){ 
    a + 10 
} 

wrap <- function(f) { function(...) { ..ret <- f(...) } } 

add10_wrap <- wrap(add10) 

trace.exit <- function() { 
    cat(sprintf("Return value: %s\n", sys.frame(-1)$..ret)) 
} 

trace(add10_wrap, exit=trace.exit) 

add10_wrap(5) 

Jednym minusem jest to, że owinięcie zawsze zwraca wyniki niewidoczne - dlatego powyższy przykład drukuje tylko formę atted wyjście.

+0

Dzięki, jest to całkowicie poprawne rozwiązanie, ale nie bardzo skalowalne. Również chcę, aby 'add10' był wywoływalny o tej samej nazwie, a nie o nazwę opakowania. Śledzenie już daje rozwiązanie dekoratora. Teraz zastanawiam się, czy można uzyskać dostęp do wartości zwracanej w tym. –