News for hackers. Stuff that matters.
Re:Conventions for Command Line Options by enriquto on Saturday August 01, 2020 @06:21PM (#24024397)
The beautiful thing of environment variables is that you can read them whenever you actually need them in your program. They pierce a hole through your call stack to the point that you need them. On the contrary, for command line arguments, you need to pass their values from the main function through whatever deep of the call stack you need them.
Re:Conventions for Command Line Options by carlmr on Saturday August 01, 2020 @06:34PM (#24024490)
I think that's an advantage. You know what goes in and out, you can see where it's passed and used. It provides transparency and fewer accidental behavioral changes.

E.g. I had a really weird bug in a script, git seemed to break for no reason, until i figured out that some other script had exported GIT_DIR which pointed to the git top level directory. The name of the variable isn't bad if want to save that directory. But git uses GIT_DIR as the location of the .git directory it should look at when it is defined.

Using environment variables is kind of like using global state, it can often cause weird behavior at a distance without a clear path of influence if you don't know exactly which environment variables are used by all your scripts.

Re:Conventions for Command Line Options by chriswarbo on Sunday August 02, 2020 @05:24AM (#24027488)
I'd say that's an example of "shotgun parsing", which is a bad idea since we might have already performed some irrevocable actions by the time we notice part of the input is missing/invalid ( https://stackoverflow.com/questions/50852226/what-does-shotg... ). It's better to check for and parse all input up-front https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-va...

I write a lot of tools in Haskell, where 'getEnv' is an "IO action" whose type prevents us using it inside most code. The simplest way to handle this ends up with a "functional core, imperative shell" model, e.g. most of my CLIs have the form (where 'interact' takes a pure String -> String function and uses it to transform stdio):

    main = do
      foo <- either error id . parseFoo <$> getEnv "FOO"
      interact (doTheThing foo)

    doTheThing :: Foo -> String -> String
    doTheThing = ...
This is also trivial to test. Some languages make it easy to replace env vars inside a single expression (e.g. bash), but others require us to set and reset the global environment, which is painful and error prone (especially if tests are run concurrently).
Re:Conventions for Command Line Options by arp242 on Saturday August 01, 2020 @08:32PM (#24025235)
In many languages you can always get at the argv list; e.g. sys.argv in Python, os.Args() in Go, ARGV in Ruby, etc.

It's not universal though; you can't in C or shell scripts for example (although, if you really want to, it's not hard to assign a global). I never had the need to inspect commandline arguments beyond the main() function though.

Re:Conventions for Command Line Options by Too on Sunday August 02, 2020 @03:17AM (#24026984)
Same thing can be said about global variables. I think any sane developer would agree it's a anti-pattern.
Re:Conventions for Command Line Options by chriswarbo on Sunday August 02, 2020 @04:57AM (#24027392)
Mutating global variables is certainly an anti-pattern, but I'm not so convinced that global constants are a problem; i.e. if we treat env vars like immutable variables (in fact I treat most variables as immutable).