It's important to realize that Julia's global variables are slow because they are generally not a good design decision, not the other way around. They could be optimized, but it's preferable to encourage taking a different approach. Julia makes other similar tradeoffs, including prohibiting eval() from interacting with the local scope. It's not that this couldn't be implemented, it's just that there are much better ways of expressing the problem that don't require this feature.
You've mentioned reasons that you use global variables, so I'll mention a few reasons that I generally try to avoid them. In short, if I use globals heavily, I find my code becomes unmaintainable immediately after writing it, and therefore the program rapidly becomes awful, bug-ridden, and impossible to add features to. Having globals simultaneously increases the code complexity and decreases readability. This is actually true of mutation in general, but mutation becomes more difficult to track when the variables that are changing are global. With local variables, you can see the explicit patterns of data-flow. With global variables, you cannot safely assume that the variable will not change during the execution of that function. Even if it is true now, someone (or even you) might later want to add some cool feature, but since they can't trace where that variable gets used, it becomes incredibly difficult to ensure that the change won't impact other parts of the code unintentionally. A second part of avoiding globals is that it makes writing good tests much harder. Ideally, a function does exactly one thing: it computes a result. In some cases, that computation is to store a value somewhere. When a function tries to do multiple things, it bugs become harder to trace, since you can't separately test the cause and the effect. Of course, I don't actually avoid them. Types, functions, STDIO, memory allocation/gc are all global because the tradeoff is not worthwhile. I'm also going to make a distinction between constants and mutatable globals. It's perfectly reasonable to have constant data accessible from the global scope. Note: some people avoid passing variables around because they assume this is a lot of work for the computer. It isn't. Like humans, it's a lot easier for the compiler to track dependencies between local variables and function parameters than to analyze a global variable. oh, and I see John beat me to finishing this reply, but I will second his recommendation of the c2.com wiki. On Mon Dec 15 2014 at 4:40:53 PM Greg Plowman <[email protected]> wrote: > Hi, > > I understand using global variables can lead to poor performance. > This is because types cannot be guaranteed? Globals could be reassigned > with different types? > > For my purpose, I set up a lot of parameters as global variables. > Then define lots of functions that have specific arguments but also use > some subset of the globals as well. > > I guess the response is going to be: do not to use globals. I get that. > However, to me it seems sometimes a natural and easy way to think about > program a solution. > > What are the alternatives: > > 1. Live with poor performance > 2. Create composite type containing the global variables, and pass > around a reference to single global variable of this composite type > - Would this boost performance? > - Would it boost performance if I didn't pass the composite-type > variable as argument, but instead access it inside functions as a global > variable? > 3. What else? > > > > To compare performance, in some functions I assigned global variables to > local variables annotated with type. Then used local variable in > function. This produced a considerable speed-up, between 3-4x faster. > > function foo(arg1::arg1type, ...) > l_var1::var1type = g_var1 > l_var2::var1type = g_var2 > ... > > x = l_var1 * ... > end > > > > Can I do something like the following with equivalent speedup? > > function foo(arg1::arg1type, ...) > g_var1::var1type > g_var2::var2type > ... > > x = g_var1 * ... > end > > This would be sort of like declaring global variables as arguments to > function but with types. > Compiler could optimise. Runtime error if type not correct. > > > > As an aside, it occurred to me that there might be 2 cases for global > variables. > > 1. globals used in interactive REPL environment, where global can be > reassigned > 2. globals used for bad or lazy or whatever programming > > Why can't we have static *type* globals? Not const but const type. > So effectively, we have 3 levels of const/variable-ness > > global x = 5 > x = 6 # OK > x = 9.1 # OK > > static x = 5 > x = 6 # OK > x = 9.1 # ERROR, must release/clear/reset x first > > const x = 5 > x = 6 # ERROR > x = 9.1 # ERROR > > > > > Cheers, Greg >
