[R] Extract the names of the arguments in an "expression"

Duncan Murdoch murdoch.duncan at gmail.com
Thu Mar 24 13:40:34 CET 2011


An improvement on my suggestion using codetools is to use

codetools::findGlobals(f, merge=FALSE)

which separates the functions and variables:

$functions
[1] "*"   "cos"

$variables
[1] "omega" "rho"

This is important, because R distinguishes between functions and 
variables by usage when it is doing a search:

mean <- 1:10
mean(mean)

will work, because the function in the second line is found in the base 
package, while the variable is the one defined on the line above.

Duncan Murdoch

On 11-03-24 8:02 AM, Duncan Murdoch wrote:
> On 11-03-24 5:03 AM, Javier López-de-Lacalle wrote:
>> Hi everybody:
>>
>> I need to get the names of the arguments in an object of class "expression".
>> I've got the following expression:
>>
>>> x<- expression(rho * cos(omega))
>>
>> Is there any function or procedure that returns the names of the arguments
>> (in the example: "rho" and "omega")?
>
> That expression also includes * and cos, which are also objects in R.  I
> presume you would like to restrict the answer to variables in a
> particular environment, e.g. the global environment, or the caller of
> your function.  The tricky bit in implementing this is that R has fairly
> rich scoping rules, so rho and omega need not live in the same
> environment, as long as both are visible where you evaluate that
> expression.  So then how do you distinguish which of the 4 objects you
> want back?
>
>>
>> I tried a rough approach implemented in the function expr.args() shown
>> below. As the function eval() needs to get access to those arguments, a
>> possible approach is as follows: 1) apply eval() to the expression "x"
>> within an empty environment; 2) get the variable names from the character
>> string containing the error message that will be returned:
>>
>> "Error in eval(expr, envir, enclos) : object 'rho' not found";
>
> I think it would be better to examine the expression, not evaluate it.
> Some expressions have side effects (e.g. plot(rho), or
> remove(list=ls())), and you may not want those side effects.
>
>>
>> 3) assign a value to the first identified variable, "rho", and apply eval()
>> again until the expression is evaluated and no error returned.
>>
>> There are some pitfalls in this approach, expr.args():
>>
>> 	i) it is a recursive procedure (I guess there must be a more
>> efficient approach);
>>
>> 	ii) it does not work if some of the arguments, for instance 'rho',
>> exist in the workspace. Despite a new environment is created to evaluate the
>> expression, objects are also searched in the parent environment. The search
>> should somehow stick to the new environment (called 'tmpe' in expr.args());
>>
>> 	iii) it does not work if the name of an argument coincides with the
>> name of a function (for instance 'gamma').
>>
>> Is there any function to do this task? If not, I would appreciate some
>> guidance to improve the function expr.args().
>
> The codetools package has functions to do things like this, though they
> are aimed at functions and packages, rather than single expressions.  I
> think you want codetools::findGlobals, e.g.
>
> f<- function() {} # a dummy function
> body(f)<- x       # containing the expression as its body
> codetools::findGlobals(f)
>
> # prints [1] "*"     "cos"   "omega" "rho"
>
> Duncan Murdoch
>
>>
>>> expr.args<- function(x)
>> {
>>     cond<- is.expression(x)
>>     if (cond) {
>>       tmpe<- new.env()
>>     } else return()
>>
>>     while (cond)
>>     {
>>       ref<- try(eval(x, envir = tmpe), silent = TRUE)
>>       if (cond<- (class(ref) == "try-error"))
>>       {
>>         if (length(grep("not found", ref[1]))>   0)
>>         {
>>           aux<- substr(ref, regexpr("object ", ref) + 8, regexpr(" not
>> found", ref) - 2)
>>           assign(as.character(aux), 1, envir = tmpe)
>>         } else stop("expression could no be evaluated but a missing variable
>> was not identified.")
>>       }
>>     }
>>
>>     ls(envir = tmpe)
>> }
>>
>> Many thanks.
>>
>> javi
>>
>> ______________________________________________
>> R-help at 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.
>



More information about the R-help mailing list