From: Duncan Murdoch <murdoch.duncan_at_gmail.com>

Date: Thu, 24 Mar 2011 08:40:34 -0400

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. Received on Thu 24 Mar 2011 - 12:50:06 GMT

Date: Thu, 24 Mar 2011 08:40:34 -0400

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

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. Received on Thu 24 Mar 2011 - 12:50:06 GMT

Archive maintained by Robert King, hosted by
the discipline of
statistics at the
University of Newcastle,
Australia.

Archive generated by hypermail 2.2.0, at Thu 24 Mar 2011 - 13:40:24 GMT.

*
Mailing list information is available at https://stat.ethz.ch/mailman/listinfo/r-help.
Please read the posting
guide before posting to the list.
*