[R] Question about function scope

Eric Berger er|cjberger @end|ng |rom gm@||@com
Tue Oct 30 21:17:30 CET 2018


Hi Sebastien,
I like Duncan's response. An alternative approach is to pass around
environments, as in the following:

bar1 <- function(e) {
  e$x <- e$y <- e$z <- 1
  cat(sprintf('bar1: x=%d, y=%d, z=%d\n', e$x, e$y, e$z))
}
bar2 <- function(e) {
  e$x <- e$y <- e$z <- 2
  cat(sprintf('bar2: x=%d, y=%d, z=%d\n', e$x, e$y, e$z))
}

foo <- function(a=1, b=2, c=0, e){
    # some setup code
  dummy <- a + b
  e$x <- e$y <- e$z <- 0

  # here is my scope problem
  if (c==1) bar1(e)
  if (c==2) bar2(e)

  # some more code
  cat(sprintf('foo: x=%d, y=%d, z=%d\n', e$x, e$y, e$z))
}

e <- new.env()
e$x <- NA
e$y <- NA
e$z <- NA

foo(c=0,e=e)
foo(c=1,e=e)
foo(c=2,e=e)


HTH,
Eric

On Tue, Oct 30, 2018 at 10:13 PM Duncan Murdoch <murdoch.duncan using gmail.com>
wrote:

> On 30/10/2018 3:56 PM, Sebastien Bihorel wrote:
> > Hi,
> >
> >  From the R user manual, I have a basic understanding of the scope of
> function evaluation but have a harder time understanding how to mess with
> environments.
> >
> > My problem can be summarized by the code shown at the bottom:
> > - the foo function performs some steps including the assignment of
> default values to 3 objects: x, y, z
> > - at some point, I would like to call either the bar1 or bar2 function
> based upon the value of the c argument of the foo function. These functions
> assign different values to the x, y, z variables.
> > - then foo should move on and do other cool stuff
> >
> > Based upon default R scoping, the x, y, and z variables inside the bar1
> and bar2 functions are not in the same environment as the x, y, and z
> variables created inside the foo function.
> >
> > Can I modify the scope of evaluation of bar1 and bar2 so that x, y, and
> z created inside the foo function are modified?
> >
> > PS:
> > - I know about "<<-" but, in my real code (which I cannot share, sorry),
> foo is already called within other functions and x, y, and z variables do
> not exist in the top-level environment and are not returned by foo. So
> "<<-" does not work (per manual: " Only when <<- has been used in a
> function that was returned as the value of another function will the
> special behavior described here occur. ")
>
> I haven't looked up that quote, but it is likely describing a situation
> that isn't relevant to you.  For you, the important part is that bar1
> and bar2 must be created within foo.  They don't need to be returned
> from it.
>
> So my edit below of your code should do what you want.
>
> foo <- function(a=1, b=2, c=0){
>
>    bar1 <- function(){
>      x <<- 1
>      y <<- 1
>      z <<- 1
>      cat(sprintf('bar1: x=%d, y=%d, z=%d\n', x, y, z))
>    }
>
>    bar2 <- function(){
>      x <<- 2
>      y <<- 2
>      z <<- 2
>      cat(sprintf('bar2: x=%d, y=%d, z=%d\n', x, y, z))
>    }
>
>    # some setup code
>    dummy <- a + b
>    x <- y <- z <- 0
>
>    # here is my scope problem
>    if (c==1) bar1()
>    if (c==2) bar2()
>
>    # some more code
>    cat(sprintf('foo: x=%d, y=%d, z=%d\n', x, y, z))
>
> }
>
> foo(c=0)
> foo(c=1)
> foo(c=2)
>
> I get this output:
>
>  > foo(c=0)
> foo: x=0, y=0, z=0
>  > foo(c=1)
> bar1: x=1, y=1, z=1
> foo: x=1, y=1, z=1
>  > foo(c=2)
> bar2: x=2, y=2, z=2
> foo: x=2, y=2, z=2
>
> Duncan Murdoch
>
> ______________________________________________
> R-help using r-project.org mailing list -- To UNSUBSCRIBE and more, see
> 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.
>

	[[alternative HTML version deleted]]




More information about the R-help mailing list