Cyrus' New Completely Useless Blog

Fun with R scoping

R's default variable scoping behavior is weird, at least coming from the Common Lisp world.

I want the equivalent of:

(defparameter *foo* "moose")

(defun doit ()
  (print *foo*))

(doit)

(let ((*foo* "bogus"))
  (doit))

foo is a dynamically scoped (special) variable in Common Lisp parlance. I can rebind foo in the let form, set its value to something and call a function that expects to see foo and have the called function see the new value of foo while but only while executing code in the dynamic scope of the LET form. Simplifying things a bit, if we call doit from code that is not called (directly or indirectly) from inside the LET form, doit will see the value of foo as "moose", whereas any code called from inside the LET form (or from code that calls it inside the LET block) the value of foo will be "bogus". This may seem confusing at first but becomes quite natural over time and is how I think about variable binding and scope.

R has its own ideas.

foo  <- "moose"

doit  <- function() {
    dput(foo)
}

doit()

local ({
    foo  <- "bogus"
    doit()
})

This gives:

{{markdown.cl|blockquote|bq-0}}
    foo  <- "bogus"
    doit()
})
"moose"

Which is obviously not what I want. Fortunately, R gives you lots of rope. There are probably many ways to achieve dynamic scoping in R, but what I've found is:

doit.dynamic  <- function() {
    dput(evalq(foo, parent.frame()))
}

doit.dynamic()

local ({
    foo  <- "bogus"
    doit.dynamic()
})

And running that gives

{{markdown.cl|blockquote|bq-1}}
"moose"
{{markdown.cl|blockquote|bq-2}}
+     foo  <- "bogus"
+     doit.dynamic()
+ })
"bogus"
>

Is this bad R juju?