21

I'd like to give a params argument to a function and then attach it so that I can use a instead of params$a everytime I refer to the list element a.

run.simulation<-function(model,params){
attach(params)
#
# Use elements of params as parameters in a simulation
detach(params)
}

Is there a problem with this? If I have defined a global variable named c and have also defined an element named c of the list "params" , whose value would be used after the attach command?

Hong Ooi
  • 56,353
  • 13
  • 134
  • 187

4 Answers4

25

Noah has already pointed out that using attach is a bad idea, even though you see it in some examples and books. There is a way around. You can use "local attach" that's called with. In Noah's dummy example, this would look like

with(params, print(a))

which will yield identical result, but is tidier.

Roman Luštrik
  • 69,533
  • 24
  • 154
  • 197
  • 4
    +1 Worth explaining what `with()` and `within()` do. In the example given, `with()` creates an environment from `params` and then evaluates the expression `print(a)` _inside_ that environment. Hence the components of `params` are visible when the expression is evaluated, without needing to `attach()` them. – Gavin Simpson Apr 27 '11 at 09:51
  • Thank you very much for the lucid answers. – statistician_in_training Apr 27 '11 at 18:47
  • So what worked in the end was 'myFun <-function(model,params){with(params),{...}}' where ... is the function body – statistician_in_training Apr 30 '11 at 19:00
11

Another possibility is:

run.simulation <- function(model, params){
    # Assume params is a list of parameters from 
    # "params <- list(name1=value1, name2=value2, etc.)"
    for (v in 1:length(params)) assign(names(params)[v], params[[v]])
    # Use elements of params as parameters in a simulation
}
Aaron left Stack Overflow
  • 36,704
  • 7
  • 77
  • 142
8

Easiest way to solve scope problems like this is usually to try something simple out:

a = 1
params = c()
params$a = 2
myfun <- function(params) {
  attach(params)
  print(a)
  detach(params)
}
myfun(params)

The following object(s) are masked _by_ .GlobalEnv:

a

# [1] 1

As you can see, R is picking up the global attribute a here.

It's almost always a good idea to avoid using attach and detach wherever possible -- scope ends up being tricky to handle (incidentally, it's also best to avoid naming variables c -- R will often figure out what you're referring to, but there are so many other letters out there, why risk it?). In addition, I find code using attach/detach almost impossible to decipher.

MichaelChirico
  • 33,841
  • 14
  • 113
  • 198
Noah
  • 2,574
  • 1
  • 18
  • 12
0

Jean-Luc's answer helped me immensely for a case that I had a data.frame Dat instead of the list as specified in the OP:

for (v in 1:ncol(Dat)) assign(names(Dat)[v], Dat[,v])

swihart
  • 2,648
  • 2
  • 18
  • 42