Erich Neuwirth
Erich Neuwirth

Reputation: 1031

Tracing functions in R

I want to trace a function so that it prints all of its arguments at the call and it prints the return value together with the arguments when it returns the result. The function trace allows to define action to be performed on entering and on exiting a function call. Is there a function returning the list of arguments within the function, and is there a way of getting the result value without doing each one of multiple branches where each branch exits the function?

in the following example, tracing should print a list of both input parameters (or the function call as text itself) at the call and the return value when the function exits in any one of the branches.

myfun <- function(a,b){
  if (a==1) return(b+1)
  if (a==2) return(b*10)
  return(b)
}

Upvotes: 5

Views: 1365

Answers (2)

duckmayr
duckmayr

Reputation: 16920

You're looking for the functions match.call() and returnValue():

myfun <- function(a,b){
    if (a==1) return(b+1)
    if (a==2) return(b*10)
    return(b)
}

trace("myfun", tracer = substitute(print(as.list(match.call()))),
      exit = substitute(print(returnValue())))
#> [1] "myfun"

myfun(1, 2)
#> Tracing myfun(1, 2) on entry 
#> [[1]]
#> myfun
#> 
#> $a
#> [1] 1
#> 
#> $b
#> [1] 2
#> 
#> Tracing myfun(1, 2) on exit 
#> [1] 3
#> [1] 3
myfun(2, 2)
#> Tracing myfun(2, 2) on entry 
#> [[1]]
#> myfun
#> 
#> $a
#> [1] 2
#> 
#> $b
#> [1] 2
#> 
#> Tracing myfun(2, 2) on exit 
#> [1] 20
#> [1] 20
myfun(3, 2)
#> Tracing myfun(3, 2) on entry 
#> [[1]]
#> myfun
#> 
#> $a
#> [1] 3
#> 
#> $b
#> [1] 2
#> 
#> Tracing myfun(3, 2) on exit 
#> [1] 2
#> [1] 2

Created on 2018-10-07 by the reprex package (v0.2.1)

As Moody_Mudskipper mentions, in the comments, you can also use quote() rather than substitute():

myfun <- function(a,b){
    if (a==1) return(b+1)
    if (a==2) return(b*10)
    return(b)
}

trace("myfun", tracer = quote(print(as.list(match.call()))),
      exit = quote(print(returnValue())))
#> [1] "myfun"

myfun(1, 2)
#> Tracing myfun(1, 2) on entry 
#> [[1]]
#> myfun
#> 
#> $a
#> [1] 1
#> 
#> $b
#> [1] 2
#> 
#> Tracing myfun(1, 2) on exit 
#> [1] 3
#> [1] 3
myfun(2, 2)
#> Tracing myfun(2, 2) on entry 
#> [[1]]
#> myfun
#> 
#> $a
#> [1] 2
#> 
#> $b
#> [1] 2
#> 
#> Tracing myfun(2, 2) on exit 
#> [1] 20
#> [1] 20
myfun(3, 2)
#> Tracing myfun(3, 2) on entry 
#> [[1]]
#> myfun
#> 
#> $a
#> [1] 3
#> 
#> $b
#> [1] 2
#> 
#> Tracing myfun(3, 2) on exit 
#> [1] 2
#> [1] 2

Created on 2018-10-07 by the reprex package (v0.2.1)

For an illustration of the difference between the two, see this Stack Overflow question.

Upvotes: 4

Eugen
Eugen

Reputation: 250

Just overlap it with .trace in name?

myfun.trace <- function(a,b){
  if (a==1) return({{"a","b"},{a,b}},{b+1})
  if (a==2) return({{"a","b"},{a,b}},{b*10})
return({{"a","b"},{a,b}},{b})    }

Upvotes: 0

Related Questions