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

Duncan Murdoch murdoch.duncan at gmail.com
Thu Mar 24 13:02:48 CET 2011


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