Skip to content

best practice(s) for retrieving a local variable from a closure

6 messages · William Dunlap, Benjamin Tyner, Barry Rowlingson +1 more

#
Greetings,

Say I have defined

  mp <- function(a) function(x) x^a

  f2 <- mp(2)

and I would like to retrieve the "a" which is local to f2. Two options 
come to mind;

  get("a", envir=environment(f2))
  eval(substitute(a), environment(f2))

I'm curious if one of these is preferred over the other in terms of 
efficiency, robustness, aesthetics, etc. Or perhaps someone can share 
another way to skin this cat, besides wrappers around eval() like

  evalq(a, environment(f2))
  with(environment(f2), a)

Also, I'd like to confirm that I have used the correct terminology in 
the subject line, that "a" is a local variable with respect to f2, which 
is a closure?

Thanks,
Ben
#
On Fri, Apr 8, 2011 at 9:48 PM, Benjamin Tyner <btyner at gmail.com> wrote:
Solutions involving eval tend to be less preferred.  "a" is termed a
free variable of f2.
#
You can also use a list-like notation with environments:
  > environment(f2)$a
  [1] 2
  > environment(f2)[["a"]]
  [1] 2
  > environment(f2)$a <- 3:1
  > f2(2)
  [1] 8 4 2

The above feels a bit like snooping where I wasn't invited.
You could do something like
  mq <- function(a) {
     force(a)
     list(getA = function()a,
          setA = function(newA) a <<- newA,
          fun = function(x)x^a
     )
  }
to make it clear that you expect people to look at or change
fun's 'a'.
  > f3 <- mq(3)
  > f3$fun(5)
  [1] 125
  > f3$getA()
  [1] 3
  > f3$setA(4:1)
  > f3$fun(3)
  [1] 81 27  9  3

I don't code like this much so haven't developed a sense of
aesthetics about these variants.

Bill Dunlap
Spotfire, TIBCO Software
wdunlap tibco.com
#
Thanks Bill and Gabor!
William Dunlap wrote:
#
On Sat, Apr 9, 2011 at 6:29 PM, Benjamin Tyner <btyner at gmail.com> wrote:

            
Once you start doing a lot of that though you may as well go the
whole OO hog and use the proto or R.oo packages...

Barry
#
On Sat, Apr 9, 2011 at 3:27 PM, Barry Rowlingson
<b.rowlingson at lancaster.ac.uk> wrote:
In the case of proto it would be this:


library(proto)
mq <- proto(fun = function(., x) x^.$a)
mq$a <- 2
mq$a # 2
mq$fun(3) # 9

or you could make explicit getter and setter functions though, as
seen, they are not really needed:

mq <- proto(fun = function(., x) x^.$a,
		getA = function(.) .$a,
		setA = function(., a) .$a <- a)

mq$setA(3)
mq$getA() # 3
mq$fun(4) # 64