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@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.

______________________________________________
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.

Reply via email to