cmbarbu
cmbarbu

Reputation: 4534

chain substitute() in R

I am trying to get names in a list twice passed in function calls, such as :

fn1 <- function(arg1){
    a<-substitute(arg1)
    print(a)
}
fn2 <- function(arg2){
    fn1(arg2[[2]])
}  
fn2(list(list(sum,sum,min),list(min,min,sum)))

And would like the print to display

list(min,min,sum)

I am trying combinations of eval() and substitute() but can't get it right.

Upvotes: 1

Views: 65

Answers (4)

cmbarbu
cmbarbu

Reputation: 4534

An answer not implying a modification of the fn2 call, inspired by heavy reading of Hadley's course

As substitute() can only be called one level up from the call, define two functions:

fn1_q <- function(arg1){
    print(arg1)
}
fn1 <- function(arg1){
    fn1_q(substitute(arg1))
}
fn2 <- function(arg2){
    exprArg2 <- substitute(arg2)
    fn1_q(exprArg2[[3]])
}
> fn2(list(list(sum,sum,min),list(min,min,sum)))
list(min, min, sum)
> 
> fn1(list(min,min,sum))
list(min, min, sum)

Upvotes: 0

cmbarbu
cmbarbu

Reputation: 4534

An imperfect solution

Seems like there are no fn1-change only answers. This is what I prefer (smaller modifification to the fn2 call) but I don't accept it as it doesn't really allows to chain substitute calls:

fn1 <- function(arg1){
    print(arg1)
}
fn2 <- function(arg2){
    fn1(arg2[[3]])
}
fn2(quote(c(list(sum,sum,min),list(min,min,sum))))

Explanation

The key is to pass a quoted expression to fn2, this prevents evaluation of the string:

fn2(quote(list(list(sum,sum,min),list(min,min,sum))))

As the call is quoted, the first item is list , the second is list(sum,sum,min), the third is ̀list(min,min,sum). I then pass arg2[[3]] to fn1:

fn2 <- function(arg2){
    fn1(arg2[[3]])
}

And printing is obvious in fn1:

fn1 <- function(arg1){
    print(arg1)
}

Upvotes: 0

Vikram Venkat
Vikram Venkat

Reputation: 671

fn2 can remain same, use this as fn1

 fn1 <- function(arg1){
    print(deparse(arg1[[2]]))
 }

but call the function using quote() around the function names min,sum,etc

fn2(list(list(quote(sum),quote(sum),quote(min)),
       list(quote(min),quote(min),quote(sum))))

Output

fn2(list(list(quote(sum),quote(sum),quote(min)),list(quote(min),quote(min),quote(sum))))
[1] "list(min, min, sum)"

Upvotes: 1

akrun
akrun

Reputation: 887213

Perhaps this may help

fn1 <- function(...) {
      lapply(substitute(...)[-1], deparse)
     }

fn2 <- function(...){
  fn1(...)[[2]]
}

fn2(list(list(sum,sum,min),list(min,min,sum)))
#[1] "list(min, min, sum)"

Upvotes: 1

Related Questions