Skip to content

scoping problems?

3 messages · Ramon Diaz-Uriarte, Brian Ripley

#
Dear All,

This is driving me nuts; I think it should be very simple (and I am sure the
answer is in front of me somewhere in ch. 3 of "S programming") but I just don't
get it.

It seems that "weights" never gets passed on to the second funciton as it
should:



myf1<-function(formula,data,weights=NULL,max.num=0,exclude.tips=NULL){
  myf2<-function(formula,data,weights){
    mf <- match.call()
    mf[[1]] <- as.name("model.frame")
    print("we get up to here")
    mf<-eval(mf,sys.frame(sys.parent())) #this is the culprit doesn't work
    w <- model.weights(mf)
    # do several things here; for simplicity just
    print(w)
    }    
# the next two lines exclude certain data points
  if(!is.null(exclude.tips)) data<-data[match(data$Tips,exclude.tips,nomatch=0)==0,] 
  if(max.num) data<-data[data$sim.counter<max.num+1,]
  myf2(formula,data,weights=weights)
}


The following is an example:
[1] "we get up to here"
Error in eval(expr, envir, enclos) : Object "x2" not found

Why doesn't it find x2? Isn't x2 right there? Note that if I define myf2 as a
function in the global env. and I call it, it works fine.

What I am doing wrong?

Thanks,

Ramon

P.S. In case it matters, I am using R 1.0.1 (under Linux)
#
On Mon, 29 May 2000, Ramon Diaz-Uriarte wrote:

            
Put a browser in myf2 and take a closer look. Your call is

Browse[1]> mf
model.frame(formula = formula, data = data, weights = weights)

Now, weights is x2, and x2 exists nowhere visible (it is a column of data).
So you want the value of weights substituted but not evaluated, and that
gets tricky, if not impossible.  So let's look for an easier way.

The usual way to do this is to assemble the call in myf1, not myf2.  As in

myf1 <- function(formula,data,weights=NULL,max.num=0,exclude.tips=NULL)
{
    mf <- match.call()
    mf$nax.num <- mf$exclude.tips <- NULL
    mf[[1]] <- as.name("model.frame")

    myf2<-function(mf) {
        mf <- eval(mf,sys.frame(sys.parent(2)))
        w <- model.weights(mf)
        # do several things here; for simplicity just
        print(w)
    }
# the next two lines exclude certain data points
    if(!is.null(exclude.tips))
    data <- data[match(data$Tips,exclude.tips,nomatch=0)==0,]
    if(max.num) data <- data[data$sim.counter<max.num+1,]
    myf2(mf)
}
 
Note that I go up two parents, as the data are in the caller of myf1.
eval.parent(mf, 2) would be neater, or you could do this in myf1.

Another idea is to use subset= rather than the data manipulations here.
#
Thank you very much to Prof. Ripley for his prompt (and very helpful)
response!!!  I think I understand the situation now; and I was happily 
surprised by the simplicity and elegance of setting to null two offending
components returned by match.call and by going up two parents to get the data.

Ramon
On Tue, 30 May 2000, Prof Brian D Ripley wrote:
-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
r-help mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html
Send "info", "help", or "[un]subscribe"
(in the "body", not the subject !)  To: r-help-request at stat.math.ethz.ch
_._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._