[R] Scoping rules

Roger D. Peng rpeng at jhsph.edu
Thu Oct 9 04:38:50 CEST 2003


I think I misinterpreted this section of the help file for get():

      If `inherits' is `FALSE', only the first frame of the specified
      environment is inspected.  If `inherits' is `TRUE', the search is
      continued up through the parent frames until a bound value of the
      right mode is found.

Should this read "parent environments" instead of "parent frames"?  I'm 
taking this from R 1.7.1.

-roger

Prof Brian Ripley wrote:

> On Wed, 8 Oct 2003, Roger D. Peng wrote:
> 
> 
>>It seems like you want in fnB
>>
>>get(AA$first, envir = parent.frame(1))
>>
>>but I'm entirely clear on why your original function doesn't work.  My 
>>understanding was that get() should search through the parent frames.
> 
> 
> Where did you get that idea from?  Argument `inherits' to get() defaults
> to TRUE and is defined as
> 
> inherits: should the enclosing frames of the environment be inspected?
> 
> Note `enclosing', not `parent'.  So the normal R scope rules apply when
> looking for an object from the frame of fnB, which as its environment (aka
> enclosing frame) is the workspace (.GlobalEnv) is to look in the local
> frame and then along the search path.
> 
> [This does seem a fairly common misconception, so if you do have any idea 
> in which document it arises it would be good to know.]
> 
> 
>>Peter Alspach wrote:
>>
>>>Dear List members:
>>>
>>>I'm using R1.7.1 (Windows 2000) and having difficulty with scoping. 
>>>I've studied the FAQ and on-line manuals and think I have identified
>>>the
>>>source of my difficulty, but cannot work out the solution.
>>>
>>>For the purposes of illustration.  I have three functions as defined
>>>below:
>>>
>>>fnA <- function(my.x)
>>>{
>>>  list(first=as.character(substitute(my.x)), second=sqrt(my.x))
>>>}
>>>
>>>fnB <- function(AA)
>>>{
>>>  tmp.x <- get(AA$first)
>>>  tmp.x^2
>>>}
>>>
>>>fnC <- function()
>>>{
>>>  x <- 1:2
>>>  y <- fnA(x)
>>>  z <- fnB(y)
>>>  c(x,y,z)
>>>}
>>>
>>>fnA() has a vector as an argument and returns the name of the vector
>>>and the square root of its elements in a list.  fn(B) takes the result
>>>of fn(A) as its argument, gets the appropriate vector and computes the
>>>square of its elements.  These work fine when called at the command
>>>line.
>>>
>>>fnC() defines a local vector x and calls fnA() which operates on this
>>>vector.  Then fnB() is called, but it operates on a global vector x in
>>>GlobalEnv (or returns an error is x doesn't exist there) - but I want
>>>it
>>>to operate on the local vector.
> 
> 
> I am not sure what you really want to do here, but R works best if you 
> pass functions an object to work on, and not the name of an object.
> Normally this sort of thing is best avoided, but if it is really needed it 
> is normally simpler to find the object in the calling function (your fnC).
> 
> 
>>>I think this is related to the enclosing environment of all three
>>>functions being GlobalEnv (since they were created at the command
>>>line),
>>>but the parent environment of fnB() being different when invoked from
>>>within fnC().
>>>
>>>My questions:
>>>
>>>1  Have I correctly understood the issue ?
>>>2  How do I make fnB() operate on the local vector rather than the
>>>global one ?
>>>3  And, as an aside, I have used as.character(substitute(my.x)) to
>>>pass
>>>the name - but deparse(substitute(my.x)) also works.  Is there any
>>>reason to prefer one over the other?
> 
> 
> deparse() is preferred.  One subtle reason is what happens with very long 
> expressions (and note deparse may give more than one line of output), 
> but the main reason is what happens with expressions such as calls:
> 
> 
>>fn1 <- function(x) as.character(substitute(x))
>>fn2 <- function(x) deparse(substitute(x))
>>fn1(log(x))
> 
> [1] "log" "x"  
> 
>>fn2(log(x))
> 
> [1] "log(x)"
> 
> 
> It is normally dangerous to use get() on the result of 
> deparse(substitute()), as the latter may be the character representation 
> of an expression and not a simple name.
>




More information about the R-help mailing list