2

I am writing a function foo(..., lev) on the base of makeContrasts function of package limma (of bioconductor):

makeContrasts(..., contrasts=NULL, levels)

I want to pass the ... argument of foo 'as-is' to makeContrasts. Here is my code:

foo = function(..., lev) {
    e = substitute(list(...))
    makeContrasts(e[[2]], levels=lev)
}

foo(a + b, design)

The reason I have used e[[2]] is that e will be list(a+b) and e[[1]] is list but e[[2]] is what I need: a + b

But the problem is that the actual argument passed to makeContrast is e[[2]] and not a + b. So what to do?

The complete parameter assignments are as below:

ct = factor(c("a","b"))
design = model.matrix(~0+ct)
colnames(design)=levels(ct)
makeContrasts(a+b,levels=design) # It works
foo(a+b, design) # Does not work
Ali
  • 9,440
  • 12
  • 62
  • 92
  • Why do you wrap `...` in `list` in the first place? – Joshua Ulrich Oct 04 '12 at 21:00
  • Can you please add your code of the function substitute? If you are returning a function, add () after the name to invoke it. – sgroh Oct 04 '12 at 21:17
  • @sgroh: `substitute` is a primitive in R. – Joshua Ulrich Oct 04 '12 at 21:23
  • I'm sorry, the valid solution is what you said in your answer :) – sgroh Oct 04 '12 at 21:29
  • STILL NO WORKING EXAMPLE. Need examples of what "a", "b" , and 'design' would be if we are to work on this further. You seem to think that the expression `a+b` will be represented internally by `e[[1]] + e[[2]]`. That is just wrong. The first element of a functional expression is the function name, in this case "+", while you probably want e[[3]] which would be the second item in the argument list. – IRTFM Oct 04 '12 at 22:52
  • no need for `substitute` as far as I can see, all you want is `makeContrasts(..., levels = lev)`, see my answer. – mnel Oct 04 '12 at 23:07
  • It now becomes clear that you did NOT want to pass only `b`. And it should be clear why we ask for complete data and code. – IRTFM Oct 04 '12 at 23:26

4 Answers4

2

Seems like you simply need to remove the list call:

> foo <- function(...) f(substitute(...))
> f <- function(...) eval(...)
> a <- 1; b <- 3
> foo(a+b)
[1] 4
Joshua Ulrich
  • 173,410
  • 32
  • 338
  • 418
  • Thanks Jashua. The problem is that f(...) is part of a pakcage and is something like this: f(...) { e = subsitute(list(...)); . . . }. The problem is that the value of e would be list(substitute(...)) and not a + b – Ali Oct 04 '12 at 21:36
  • @AliSharifi: that's confusing. Can you update your question with a definition of `f`, some sample data, and the expected output? – Joshua Ulrich Oct 04 '12 at 21:53
  • @AliSharifi: please provide values for `a`, `b`, and `design`. – Joshua Ulrich Oct 04 '12 at 22:38
1

A may be over simplifying the problem, but does the following not just work

foo = function(..., lev) {
 makeContrasts(...,levels =lev)
}

foo(a + b,b+c, lev =letters[1:3])


## Contrasts
## Levels a + b b + c
## a     1     0
## b     1     1
## c     0     1

using your example

I don't appear to be oversimplifying.

If ... contain the arguments to be passed to another function, then all you need is to pass ... to that function. ...

ct = factor(c("a","b"))
design = model.matrix(~0+ct)
colnames(design)=levels(ct)
makeContrasts(a+b,levels=design) 
## Contrasts
## Levels a + b
##  a     1
##  b     1
foo(a+b, lev = design)
## Contrasts
## Levels a + b
##  a     1
##  b     1
mnel
  • 113,303
  • 27
  • 265
  • 254
  • Thanks. Your simple answer was perfect. However I don't understand how R interprets 'a + b' while these objects does not exist, and what to do if I want to modify the ... argument and then pass it over? – Ali Oct 04 '12 at 23:08
  • I will make a new question how R interprets ... arguments – Ali Oct 04 '12 at 23:15
  • Don't --- there are questions already http://stackoverflow.com/questions/3414078/unpacking-argument-lists-for-ellipsis-in-r http://stackoverflow.com/questions/3057341/how-to-use-rs-ellipsis-feature-when-writing-your-own-function http://stackoverflow.com/questions/3142731/r-using-a-list-for-ellipsis-arguments search [r] ellipsis – mnel Oct 04 '12 at 23:17
0

If you are trying to pass a + b as a string, add quotes. You could also set an object to be "a + b" and pass the object.

Bob
  • 1
  • This is not the case. I am not trying to pass a + b as an string, but it would be an "unevaluated" statement. The true input to the f(...) is a + b and not "a + b" – Ali Oct 04 '12 at 21:07
0
a=3, 
b="test"
 foo = function(...) {
    e = substitute(...)
     eval(e[[3]]) 
}

foo(a + b)

foo(a + b)
[1] "test"

As pointed out by others, your expectations remain unclear. Possibly you do not want evaluation and only want the symbol:

foo = function(...) {
    e = substitute(...); str( e[[3]])
    return(e[[3]]) 
}

foo(a + b)
# symbol b
#b
IRTFM
  • 258,963
  • 21
  • 364
  • 487