6 ms·
I think doing away with global variables is not a very good idea. While using globals is usually a bad idea, there are many instances where globals are appropri
by slaymaker1907 8y ago
I think doing away with global variables is not a very good idea. While using globals is usually a bad idea, there are many instances where globals are appropriate (at least for languages supporting mutability). People who say they never use globals usually do use globals and are just trying to convince themselves they are not because they heard they were bad from somebody.
The entire Spring framework is IMO an elaborate construction built so that engineers could use global variables without their managers finding out. There is little to no difference between carefully using global variables and Spring dependency injection except syntax.
The best solution I have ever seen to global variables is definitely parameterize with Racket (https://docs.racket-lang.org/guide/parameterize.html https://docs.racket-lang.org/guide/parameterize.html). I don't think Racket was the first language to come up with this, but it was the first one I am aware of. The basic idea is that you define some global with a default value. However, you can call parameterize to change the value for the duration of some input function. It is made thread safe by using thread local memory. It then resets the parameter back to the default value at the end of the function.
On the other end of the spectrum, I think Rust also has a very good implementation of globals. It will let you use global variables, but you have to declare it as mutable, use some form of locking, or use an UnsafeCell. Additionally, you have to mark your code as unsafe any time you try to read or change this global variable.
- omeid2 8y ago> There is little to no difference between carefully using global variables and Spring dependency injection except syntax. Until you need to write unit tests.
- darrenf 8y ago> The best solution I have ever seen to global variables is definitely parameterize with Racket (https://docs.racket-lang.org/guide/parameterize.html https://docs.racket-lang.org/guide/parameterize.html). I don't think Racket was the first language to come up with this, but it was the first one I am aware of. The basic idea is that you define some global with a default value. However, you can call parameterize to change the value for the duration of some input function. Isn't that basically Perl's `local`?
- tripa 8y agoIt is, but Lisp did have it first, even if not through Racket.
- eslaught 8y agoYes, it's called dynamic scoping, and for a long time it wasn't believed that the other option (what we call lexical scoping today) could even be implemented efficiently. https://en.wikipedia.org/wiki/Scope_(computer_science)#Dynamic_scoping https://en.wikipedia.org/wiki/Scope_(computer_science)#Dynam...
- chrismorgan 8y agoI find myself sometimes wishing that Rust genuinely didn’t have globals. There are some things where it’d cause pain, and some places where I’m not sure what you’d replace it with (lazy_static, for example), but I find that Rust actually makes it too easy to do globals and thus have unexpected side-effects (e.g. command line arguments, environment variables, working directory—I would genuinely prefer these things to be passed to main for me to use at my discretion), although in most places the culture is against using them, which saves it from being too much of a problem. Yet still, strict functional purity can open up some delightful optimisations and avoid various bugs, just like how putting error handling into the type signatures helps clarify things and avoid all kinds of bugs. I’d like to see what Rust would be like with even fewer, or no, globals.
- omaranto 8y ago> I don't think Racket was the first language to come up with this. Racket's parameters are just dynamically scoped variables. Most Lisps have them. The older Lisps actually predate lexically scoped variables and had dynamically scoped variables exclusively! Emacs Lisp is not even that old and only had dynamic scope until relatively recently.
- soegaard 8y ago> Racket's parameters are just dynamically scoped variables. More or less. Racket's parameters also work with multiple threads and cooperates with continuations. In Scheme it is common to see `fluid-let` to handle classic dynamically scoped variables.
- omaranto 8y agoI think most Common Lisp implementations that provide threads, make dynamically-scoped variables (called "special variables" in Common Lisp) thread-local.
- amedvednikov 8y agoV consts are a bit more powerful. For example you can define structs: const red = gx.Color{255, 0, 0} or even call simple functions that only return values const red = gx.rgb(255, 0, 0)