3 ms·
I think you misunderstand my point. Forget mutation; that was a minor technicality, but isn't important for my point. My point is that environment variables ar
by chriswarbo 1y ago
I think you misunderstand my point. Forget mutation; that was a minor technicality, but isn't important for my point.
My point is that environment variables are "dynamic variables" (AKA they are "dynamically bound", AKA they have "dynamic scope" https://en.wikipedia.org/wiki/Scope_(computer_science)#Dynamic_scope https://en.wikipedia.org/wiki/Scope_(computer_science)#Dynam... ). That is very much not like globals.
For example, consider the following script:
#!/usr/bin/env bash
# The export keyword turns a shell variable into an env var
export foo='hello'
echo "BEFORE '$foo'"
# Invoke the env command as a subprocess, to list all of the
# environment variables it's inherited. Filter it using grep.
foo='goodbye' env | grep 'foo='
echo "AFTER '$foo'"
Our hypothesis will be that env vars are "globals", i.e. that there's a place in memory that all these occurrences of the name `foo` are referring to. Under this hypothesis, there are several plausible outputs that the above script might give:
Perhaps the `foo='hello'` assignment sets the memory referred to by foo to the value `hello`; then the `foo='goodbye'` assignment sets that memory to `goodbye`. In which case we'd expect to see:
BEFORE 'hello'
foo=goodbye
AFTER 'goodbye'
On the other hand, perhaps the `foo='goodbye'` assignment fails (maybe since that memory already contains the value `hello`?), in which case we would expect to see something like:
BEFORE 'hello'
foo=hello
AFTER 'hello'
It might even be the case that some obscure issue causes both assignments to fail; but, by sheer coincidence, the memory `foo` is referring to just-so-happens to already contain the value `goodbye`. In that case, we'd expect to see:
BEFORE 'goodbye'
foo=goodbye
AFTER 'goodbye'
Now, let's test our hypothesis by performing the experiment, i.e. by executing the script:
BEFORE 'hello'
foo=goodbye
AFTER 'hello'
Uh oh, that doesn't correspond to any of the possibilities I gave! With a little more thought, we might see that this output cannot be produced using a single memory location; since the value `hello` was not "forgotten", even though foo had the value `goodbye`.
The answer is that env vars are not globals; instead, they are "dynamic variables". Normally, programming languages implement dynamic variables internally by traversing the stack; e.g. in Lisp it would look something like:
(let ((foo "hello"))
(echo (format "BEFORE '%s'" foo))
(let ((foo "goodbye"))
(echo (filter (has-prefix "foo=")
(something-like-the-locals-function-in-python)))
(echo (format "AFTER '%s'" foo)))
However, that wouldn't work across process boundaries; which is why env vars get copied (perhaps with additions/removals) when subprocesses are created.
(I go into more detail in the blog post I linked ;) )
PS: You may be wondering why I wrote a script containing `foo='goodbye'` if I previously said "Forget mutation". That is because we are not mutating the value of `foo`; we are entering a new scope, where `foo` has a different value; but the old scope with the old value still exists; we saw as much when it outputs `AFTER 'hello'`. Similar to how in "lexical scope" (a more common form of scoping, which is different from global scope and from dynamic scope) we can write a whole bunch of functions with arguments called `x`, but that doesn't count as mutating the value of `x`. Or we can even call the same function, perhaps recursively, with different values for the same argument; but those new values are not mutations of the old ones, despite them having the same name and being defined in the same place (like dynamic scope, lexical scope is also typically implemented within a process by using stack frames).
- peter_d_sherman 1y agoIf I am understanding you correctly, you are stating that a given shell, specifically a subshell -- may not in some cases see the same shell variables as other shells... That is true. Subshells may not in some cases see the same shell variables as in other shells. I'm not contesting this. But let's suppose that we have not a shell variable, but a socket... A socket that any program can open -- and retrieve a web page from... For the simplicity of thought, let's say that the data for that web page is always static. It always returns the same web page; the same data for that web page... So now my question to you: Can that socket, which can be opened by any program, mimic a global variable? ? Why or why not? ? Or perhaps an even simpler question... Let's suppose that there's a file on filesystem... globally accessible to be read and written to by all programs... Can that file's presence mimic a global variable? ? Why or why not? ?
- chriswarbo 1y agoYour filesystem question is actually far from simple, due to all manner of edge-cases. In particular, since you say things like "globally accessible to be read and written to by all programs", I'll assume we're not talking about chroot, bind-mounts, etc. I'll also ignore the case where we open a file path, then delete the path, then open the path again; since that gives us two separate files, though the first can no longer be accessed via its original path (we can hand-wave these by pretending the path has moved to /proc/<pid>/fd or something). If we ignore those, and just stick to normal FS operations in an ordinary Linux process, then those filesystem objects are globals, since the filesystem is a global namespace: a name (or path, in this case) will always refer to the same filesystem object (modulo the caveats above). --- > If I am understanding you correctly, you are stating that a given shell, specifically a subshell -- may not in some cases see the same shell variables as other shells... No, that's not what I'm saying. I'm talking about env vars: bound via `execve`, stored near the spawned process's stack). Not shell variables, or any other language-specific/internal variables (whether a shell, like Bash, or otherwise). That's the entire reason why my code example used `export`.
- peter_d_sherman 1y ago