You don't get a vote in whether or not to agree; I was describing how the
language works. Now, you might wish it worked differently, but I wasn't
answering the question "should this work differently", but rather, "why
does the way it works now not allow code outside of functions".
This is a very useful feature - otherwise either all your
initializations have to be constants (but often you want to read from the
registry for example) or you need have a special ModuleInit function and
hope all the clients remember to invoke it.....
If you need to do that, you do it yourself, which is pretty easy.
The only thing needed: there is a moment when for the first time a
function in that module gets called. Before that happens, the BEGIN block
is guaranteed to have run. If no function is called, the BEGIN block may
get run or may not, no guarantees.
I think that is a simple but useful feature.
It's a horrible misfeature for C.
Let's walk through why.
Let's say you wanted to do this. It's easy for you to do it yourself; you
start every function with
my_init();
which does initialization if it needs to.
Now... What happens to the performance of all of your functions when you add
that to them? Why, it gets worse. For every function. Meaning that you are
silently adding a significant cost to every function in the module.
That's not how C generally does things. If you want to call an initializer
at the beginning of every function in a module, you are welcome to do so, but
C does not favor "solutions" in which everyone in the entire world has to pay
a potentially significant cost for every program they ever build just because
you wanted this feature once.
In languages like perl or ruby, a feature like this makes sense, because each
module of code is "loaded" at a specific time. In C, you can do this by
writing your own little initializers all over, or you can do things that are
more clever but less portable.
If you want to see a reasonable example of how this might be solved in a real
system in C, in a way that is much cleaner and better defined than the vague
"let's just run code outside of functions", look at how the Linux kernel
handles initialization functions.
It's clearer, it's better-designed, and it has a number of other advantages
(such as allowing the kernel to dump the executable code for those functions
once it's done running them).
-s