[R] Scoping rules
Prof Brian Ripley
ripley at stats.ox.ac.uk
Thu Oct 9 08:45:03 CEST 2003
On Wed, 8 Oct 2003, Roger D. Peng wrote:
> 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.
It should read `enclosing' not `parent' for a start.
Thanks: we will try to get this consistent.
>
> -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.
> >
>
>
--
Brian D. Ripley, ripley at stats.ox.ac.uk
Professor of Applied Statistics, http://www.stats.ox.ac.uk/~ripley/
University of Oxford, Tel: +44 1865 272861 (self)
1 South Parks Road, +44 1865 272866 (PA)
Oxford OX1 3TG, UK Fax: +44 1865 272595
More information about the R-help
mailing list