4

I have the following snippet:

y <- 1
g <- function(x) {
  y <- 2
  UseMethod("g")
}
g.numeric <- function(x) y
g(10)
# [1] 2

I do not understand, why it is possible to have access to y in g.numeric <- function(x) y. To my understanding y's scope is just within the definition of the generic (g <- ...). Could anyone explain to me, how that is possible?

MrFlick
  • 195,160
  • 17
  • 277
  • 295
ruedi
  • 5,365
  • 15
  • 52
  • 88

1 Answers1

4

The description of this behavior can be found in the ?UseMethod help page

UseMethod creates a new function call with arguments matched as they came in to the generic. Any local variables defined before the call to UseMethod are retained

Thus any local variables defined in the function calling UseMethod are passed along to the next function as local variables. You can see this with

g.numeric <- function(x) ls()  #lists all variables in current environment
g(10)
# [1] "x" "y"
g.numeric(10)
# [1] "x"
MrFlick
  • 195,160
  • 17
  • 277
  • 295
  • Does `UseMethod` even come into play here? E.g.: `x <- "global"; test <- function() x; test(); rm(x); test()` Doesn't R just search in parent environments if it can't find the object in a local scope? – thelatemail May 22 '15 at 04:23
  • 1
    @thelatemail Notice that the value of `y` is changing in the `g()` function and this is the value that's passed along, not the value in the global environment. R will normally search parent environments where the function was *defined*, not *called*. This particular behavior is unique to `UseMethod`. – MrFlick May 22 '15 at 04:26
  • I just don't understand why `y` would ever be `1` when calling `g(numeric())` as `y <- 2` sets it inside that function. `g.numeric(numeric())` similarly doesn't change `y`. – thelatemail May 22 '15 at 04:38
  • 1
    @thelatemail try: `y <- 1; g <- function(x) {y <- 2;g.numeric(x)}; g.numeric <- function(x) y; g(10); #[1] 1`. Notice the only difference is changing `UseMethod("g")` to `g.numeric(x)` which you might expect to be the same (and they are not). – MrFlick May 22 '15 at 04:42
  • 1
    Right - that's a nice example. Sooooo.... because `g.numeric` gets defined in a global environment, it goes hunting in the global rather than local space first? I think I have it through my thick skull now. – thelatemail May 22 '15 at 04:46
  • Thanks a lot for great explanation and the example! – ruedi May 22 '15 at 07:13