Why don't you want to do this? timesDefineInside <- function(foo, bar...) { foo * bar }
It seems like the obvious solution to your problem. Hadley On Sun, Oct 19, 2008 at 8:34 PM, Sietse Brouwer <[EMAIL PROTECTED]> wrote: > Dear R-helpers, > > I've got two functions; callTimes() calls times(), passing it an > optional argument (bar) by name (bar=harry). times() then believes it > has been passed a name, rather than a value — but I want the value, > not the name. > Worse, if I evaluate the name, it is evaluated in the environment > times() was defined, not where it is called. > How can I call times(), defining its optional argument as a variable, > and have times() know the variable's value (at the moment of calling)? > > Below some code: > (1) The basic case > (2) A working kludge-around (but I'm still looking for the Right Way.) > (3) A bunch of variants, so that you may get an idea of the behaviour > involved. > > (3 starts from the simplest case and builds up from there. Think of it > as background reading.) > > Actually, I'll put (1) up here: > > ######################## > ## (1) The basic case ## > > ## The calling function > ## passes an optional argument (bar), as a variable (bar=harry). > callTimes <- function(tom, harry) { > print(match.call(expand.dots=TRUE)) # callTimes(tom = 2, harry = 7) > timesDefineInside(foo=tom, bar=harry) > } > > ## The called function > ## does not explicitly ask for bar. > timesDefineInside <- function(foo, ...) { > # Checks to ensure this code is only executed if bar is given. > print(match.call(expand.dots=TRUE)) # times(foo = tom, bar = harry) > bar <- match.call(expand.dots=TRUE)$bar > print(foo) # [1] 2 > print(bar) # harry > print(mode(bar)) # "name" > print(eval(bar)) # [1] 13 > foo*bar # Error in foo * bar : non-numeric argument to binary operator > } > > harry <- 13 # Now, let's see whether it thinks harry==13, or harry==7 > callTimes(2, 7) > ## For the output, see the above inline comments. > > ## And THERE we have my problem. I have yet to find a way to call a function, > ## give one of the optional arguments as argument=variable, and have it pick > up > ## on that variable's *value*, rather than its name. (It's not even the > ## reference it picks up on: as you can see, if I evaluate the name, it uses > ## the definition environment, rather than the calling environment. > > (For the work-around, scroll down.) > > A second question, not essential: I spent a while searching on this > topic, and found myself unsure of the terminology. Tried a number of > things, found nothing, now I'm not sure whether that's because I > didn't know the right words. How would you phrase/define this problem? > > Kind regards, and thanks in advance, > > Sietse > Sietse Brouwer > > ################# > ## Code below. ## > ## Two comment-signs for comments, one for output, none for input. > > ########################## > ## (2) A working kludge ## > > ## I can kludge around it by using > callTimes <- function(tom, harry) { > timesArgs <- list(foo = tom, bar = harry) > do.call(times, timesArgs) > } > ## ; but is there a Right Way, too? > > > ############################################################ > ## (3) Some variants, starting from the simplest case... ## > ## ...and increasing in complexity. > > > ## (3.1) This is the function I have trouble with: I can't get it to get bar > ## from the arguments. > times <- function(foo, ...) { > print(match.call(expand.dots=TRUE)) > # Some checks and a guard statement. You can safely assume that if there > # ain't no bar argument (bar fight?), this part will not be reached. > foo*bar > } > > ## here we run it, and see that it gets bar not from > ## the argument list, but from the defining environment. > ls(bar) > # Error in as.environment(pos) : no item called "bar" on the search list > times(foo=2, bar=3) > # times(foo = 2, bar = 3) > # [1] Error in times(foo = 2, bar = 3): object "bar" not found > ## Somehow, it doesn't cotton on to the fact that there's a bar > ## in the argument list. > bar <- 5 > times(foo=2, bar=3) > # [1] 10 > ## Ah. it looks for bar in the environment where the function was defined, not > ## in the one where it is evaluated. Lexical scoping, plus a rule of > ## inheritance/who's-your-parent-now that I don't quite understand. > > ## (3.2) Now we try explicitly getting it from the argument list. > rm(bar) > timesDefineInside <- function(foo, ...) { > print(match.call(expand.dots=TRUE)) > # again, imagine checks here. > bar <- match.call(expand.dots=TRUE)$bar > foo*bar > } > timesDefineInside(foo=7, bar=11) > # [1] 77 > > ## So this works, and all is well, nay? Nay. Turn thou to (1) to see what > ## doth happen when we call timesDefineInside from inside another function. > > -- > Sietse Brouwer -- [EMAIL PROTECTED] -- +31 6 13456848 > Wildekamp 32 -- 6721 JD Bennekom -- the Netherlands > MSN: [EMAIL PROTECTED] -- ICQ: 341232104 > > ______________________________________________ > R-help@r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code. > -- http://had.co.nz/ ______________________________________________ R-help@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.