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.