I can think of plenty of legitimate cases where one would use globals in a dynamically linked library. Most stdlib(libc) implementations have plenty of globals in them (think for a bit, you'll find enough of them being documented, like stdin/stdout/stderr). The most common case is where the library initializes a shared resource or object of some kind (of which you only need one instance that can be used by everything else). It's especially important if it's a resource which takes a while to initialize and doing so would cost plenty of resources. Or it could be a global cache of sorts which is again costly to recreate it time and thus it would defeat the whole purpose of the cache. On the other hand, in most OSes, you can load the same library multiple times if you really want to avoid such unique globals.
I can't think of a single implementation of any language which doesn't use globals in some way, no matter how hard they may try to not use them. Shared resources are everywhere (your CPU, RAM, GPU, NIC are such resources...), get used to it!
>>1
What about using a language with a decent module system? #lang racket/load
(module a racket
(provide set!-d get-d)
(define d 2)
(define (set!-d x) (set! d 2))
(define (get-d) d))
(require 'a)
(get-d) ; => 2
(set!-d 3) ; d = 3
(get-d) ; => 3
d ; Unbound variable
(in before "eww parens" and "lol toy language", Racket's not the only language with non-crappy modules (Python's is pure _shit))
>>3 Most stdlib(libc) implementations have plenty of globals in them
Everyone cries about strtok using a global variable to store the string.
Using globals without mutexes considered harmful.
>>5
It depends on what kind of global and how it's handled (to assure thread-safety). strtok is so terrible that I've written my own implementation which is thread-safe. However, certain kinds of globals such as those which either contain read-only data, or data which is modified in an atomic and thread-safe fashion are usually fine. Also, dynamicly scoped "globals" as Common Lisp has are pretty safe too. Global resources which are managed through a thread-safe API are also fine (even if there's only one resource in the underlying code).
>>1
It's easy to use globals even in C libraries without problems. Present a problematic scenario and I'll give you a solution.
>>3
Global variables are different from (shared) system resources. More importantly, system resources are managed differently by the language and its standard library than the global scope is in virtually every language. Even when the global scope contains system resource facilities it's almost always an interface to manage the resource rather than the resource itself (common exceptions are per-process allocated resources, such as stdin/stdout) and it's a standard part of the language/target platform; never a gotcha that some library developer springs on you.
Name:
Anonymous2010-12-26 14:24
>>3
Sorry for my lack of details in >>1; I was referering to libraries who this kind of thing (I won't name it... *cough*OMG GLORIOUS OpenGL*cough):
int main()
{
int c;
object_initiate("poop/somefile.txt");
while((c = object_get()) != -1)
{
...
}
object_destroy();
}
>>10
That's troublesome since if your goal is to go through all the "objects", object_get might be called from another thread, or maybe even within that loop somewhere, which might lead to some objects being skipped in that loop. It's essentially a case of using globals for short-lived data, for which local variables should be used instead. Globals should be used for data which lives mostly as much as the entire code does (in memory).
THIS THREAD HAS BEEN CLOSED AND REPLACED WITH THE FOLLOWING: Subject: Replacing all cars with cdrs Name: Email: mailto:sage Message: (let loop ((xs '(1 2 3 4 5)) (r '())) (if (null? xs) r (loop (car xs) (+ (car xs) (car xs)))))
car: expects argument of type <pair>; given 1
It doesn't work.
Name:
Anonymous2010-12-26 23:09
>>17
Here's some evil, but non code breaking code:
#.`(cl:defpackage #:inverse-lisp
(:use #:cl)
(:shadow #:car #:cdr)
(:export
,@(cl:loop :for sym :being :the :external-symbol :of (find-package :cl)
:collect sym)))
(cl:in-package #:inverse-lisp)
(defun car (list) (cl:cdr list))
(defun cdr (list) (cl:car list))
Of course, one could also redefine (this breaks the standard, but would actually work in most implementations) cons/car/cdr such that the positions would be reversed, but you'd just break most of the existing code, not to mention that cons/car/cdr are pretty much always inlined in any serious implementation (car/cdr being just a simple asm instruction in most cases, while cons just calls a quick allocator and assigns the 2 fields.
>>19
Well, my code doesn't break any existing code as it just defined a new package which is just like the usual CL one, but with car and cdr having reversed roles. No code is actually affected, but if someone chooses to use this modified implementation, they must use the reversed car/cdr properly if they don't want to break their code.