2

coming back to this post years later to add yet another warning: DONT DO THIS

I am trying to store a variable from a function in the global environment, but none of the solutions I found SO post or different SO post worked for me. This is an extremely simplified example to illustrate my problem. I cannot just use the <<- to make v global because my actual function creates several dozen variables.

Code (main_file.R)

source("function_me.R")
#environment(doGlobalThing) <-parent.frame(2) #didnt work
doGlobalThing()
v #cant get to this var from the global environment

Code (function_me.R)

doGlobalThing<-function(){
  #eval(v<-'hi',env=parent.frame(2)) #tried this, didnt work
   v<-'hi'
}
Rilcon42
  • 9,584
  • 18
  • 83
  • 167
  • 1
    Do not work against the design of the language. Learn functional programming. – Roland Jun 01 '16 at 07:26
  • @Roland, Can you explain (briefly) why my idea of creating a new set of global variables is wrong in an EMPTY global environment based on some tenet of functional programming? – Rilcon42 Jun 01 '16 at 18:58
  • 2
    There is absolutely no advantage of doing this over returning what you need from the function, e.g., in a list. However, as you note, it creates a burden for you that you have to remember that your function has site effects and to ensure that this doesn't create problems. And of course, that means that you can't really give your code to others or reuse it easily. The only situation where doing this might make sense is if you were trying to assign by reference and modify in place, but then you should do it in a different environment and not the global one (or use reference classes). – Roland Jun 02 '16 at 07:12

1 Answers1

8

You could use assign:

assign("v","hi",envir = globalenv())

This requires that you have the name of the target global variable as a string, but it can be easy to do this even with a vector of dozens of such things.

This question discusses the differences between assign and <<-. The chief difference is that assign lets you specify the environment -- so it is easy to use it to store data in a non-global but persistent environment so that you could e.g. emulate static variables in R. While it is possible to use assign to modify the global environment, you should be aware that it is seldom a good thing to do so. There is too much of a danger of accidentally overwriting data that you don't want to have overwritten. Code which makes heavy use of global variables can almost always be refactored into cleaner code which doesn't. If you need to get a lot of heterogeneous data from a function to the calling environment, the cleanest solution would be to return the needed data in a list.

The accepted answer ends its discussion of <<- and assign with a good quote:

The Evil and Wrong use is to modify variables in the global environment.

Community
  • 1
  • 1
John Coleman
  • 51,337
  • 7
  • 54
  • 119
  • This is true, but I was hoping for a more general solution....preferably a method to make all variables created in the function global with one call – Rilcon42 Jun 01 '16 at 06:06
  • I could just as easily use `<<-` as your solution, although yours was new to me – Rilcon42 Jun 01 '16 at 06:06
  • TI do it in one call, use `assign` in either a `for` loop or an `apply` function. But there is still the question of whether the side effect is worth it. It is often better to store values that must be stored and accessed from the global environment in either a list in the options, or in a different environment. – Benjamin Jun 01 '16 at 07:05
  • 2
    I've downvoted this because you didn't include a strong warning that having a site-effect like this is bad. If there happens to be a `v` variable in the global environment it is overwritten, which can lead to bugs, which are very hard to find. – Roland Jun 01 '16 at 07:29
  • 2
    @Roland Good points. I've edited it to include the appropriate warning. – John Coleman Jun 01 '16 at 11:11
  • This is a very good answer. Everyone posts the ``<<-`` as the main answer to questions like these, often making it the first and most popular answer that pops up in the search, while I hardly see ever using it as a good practice. ``assign`` should always be the way to go, even if on ``globalenv()`` – runr Jul 15 '20 at 16:06