Hacker News new | past | comments | ask | show | jobs | submit login

Calling env vars 'global mutable variables' is pretty misleading. The example C code is a terrible strawman, and makes it appear that the author is simply unaware of some core compsci/programming concepts.

Environment variables behave much more like dynamic variables (AKA dynamically scoped/bound variables), rather than global variables https://en.wikipedia.org/wiki/Scope_(computer_science)#Dynam...

In particular, we can override env vars for a particular call, without affecting anything else. For example, consider the following script:

    echo "BEFORE $FOO"
    FOO=bar printFoo
    echo "AFTER $FOO"
If we run this script with 'FOO=foo', and assuming that the program 'printFoo' simply prints the 'FOO' env var, we will get:

    BEFORE foo
    AFTER foo
The variable 'FOO' wasn't mutated (since the value remains the same across lines 0, 2 and 3); it's also not globally scoped (since line 1 saw a different value). Rather, each process is run with its own environment, whose initial contents is inherited from the scope that invokes the process; plus extras/overrides, like 'FOO=bar' above.

Env vars are mutable, and mutating an env var acts differently to mutating a dynamic variable: dynamic scope looks up variables on the call stack, so mutations high up the stack will be visible after returning. Instead, env vars are copied from parent to child at each new scope (process), so mutations are only visible to that process and any subsequent subprocesses. In fact, that makes env vars even less 'globalish' and 'mutableish' than ordinary dynamic variables!

For example: if 'printFoo' finished by mutating 'FOO' to equal 'baz', it wouldn't affect the above script at all. Even line 2, which "inherits" the script's FOO, would only be mutating its own copy of 'FOO', which doesn't affect the script's variable.

In any case I highly recommend to avoid mutating env vars, for the same reason I avoid mutating any variables, regardless of language; unless there's a specific reason to. If we treat env vars in an immutable way, then they act exactly like dynamic variables.

As an example of dynamic variables, consider the following Lisp code:

    (write-line (concatenate "BEFORE " FOO))
    (let ((FOO "bar"))
    (write-line (concatenate "AFTER " FOO)
The '(let ((FOO "bar")) ...)' construct acts like the 'FOO=bar ...' of the script.

Not only do I find env vars very useful for config, I also find dynamic scope is very under-utilised in "proper" (non-shell) languages. For example, dynamic scope is a great way to do dependency injection: rather than passing around extra arguments, or adding a bunch of private fields to objects, etc. we can just reference the dependency with a dynamic variable, and open a new scope whenever we want to set its value (at an application's entry point, or in a test, etc.)

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact