3 ms·
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
by chriswarbo 6y ago
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-shotgun-parser-mean 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-validate 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).