Search code examples
rscopeclosuresenvironment

Shouldn't envir = parent.env(environment() protect my function from being modified despite what happens in the global environment?


So I wrote the following function:

deck <- function(){
face <- c("Ace","Two","Three", "Four",
                   "Five", "Six", "Seven", "Eight",
                   "Nine","Ten", "Jack", "Queen", "King")
hearts <- replicate(13,"Hearts")
diamonds <- replicate(13, "Diamonds")
clubs <- replicate(13, "Clubs")
spades <- replicate(13,"Spades")
suit <- c(diamonds, spades, hearts, clubs)
value <- c(1:13)
assign("deck", data.frame(face,suit,value), 
       envir = parent.env(environment()))
return(deck)
}

And it works fine, it basically shows me a deck of cards.

However, I thought that the argument envir = parent.env(environment() meant that if I wrote something afterwards, for example:

deck <- "Whatever"

the function deck() function would still be working - because the object deck was only modified in the global environment, but not on the parent environment. But that's not happening.

What's happening is:

  1. I enter the code, and it works fine - it shows me a deck of cards
  2. I assign something else to deck
  3. When I type deck() again, it says that R couldn't find that function.

Can someone please explain me why?

And how do I properly use parent.env(environment) to sort of protect my function from suffering any modifications? If I'm not mistaken, that process is called "closure" - that's what I'm interested in.


Solution

  • You are looking for the attach function and not the assign function. eg:

    attach(list(deck = function(){
      face <- c("Ace","Two","Three", "Four",
                "Five", "Six", "Seven", "Eight",
                "Nine","Ten", "Jack", "Queen", "King")
      suit <- c("Hearts", "Diamonds", "Clubs", "Spades")
      cbind(expand.grid(face = face, suit = suit), value = 1:13)
    }))
    

    Now this is include in your searchpath. So if you change the function, you will mask this one. But otherwise it is available to you.

    ie:

    deck() # Gives you the deck of cards
    deck <- "whatever"
    deck # gives you whatever
    deck() # gives you the deck of cards