System Scripts
Computers are built on top of abstractions, I would perhaps even be willing to say that it is one of the few things in life that are pure abstractions all the way down. And while languages are excellent at that, some parts of the current computer systems are rather more lacking.
If I were to tell you that I want a trivial program, that takes two numbers and adds them, how much work is that gonna be?
For one, I didn't say what "form" the program should take, how the inputs are specified, is it even a GUI program, HTTP API server or a CLI script, does that matter at all though? Does any of that matter in the slightest in the context of me needing two numbers added? I'd boldly claim that it does not.
What I'd wish to exist is a system where I could declare the three lines of:
x: Number
y: Number
x + y
or perhaps even just:
x + y
automatically inferring that x and y are free variables that need to be added
therefore are probably numbers in this context, perhaps other things depending
on what the +
would be.
Then I'd expect this thing to be callable immediately with
adder --x 2 --y 3
why would parsing flags and inputs be something I need to think about and implement myself, when POSIX supposedly standardized how these things should work.
and how about a magic trick:
curl \
sys://localhost/adder
-H "Content-Type: application/json" \
--data '{ "x": 2, "y": 3 }'
> 5
We could take a few notes from the wonderful project Mininterface by the awesome folks at NIC.CZ.
Which isn't far from this idea, and also automatically provides a GUI or TUI, and checks the $XDG_CONFIG_DIR for config files to override the defaults.
All the config files, flags, environment variables, parameters and STDINputs are just one and the same, they are but parameters to some algorithm within.
I'd like to stretch this idea however, to the absolute limit of human and computer interaction with scripts, libraries and programs. Using Common Lisp functions that take typed optional keywords is another example that closes in to what I'm after, however I'd like to extract this into the entire system.
As an example let's write a library:
# hello-worlder.sys
name: String
(print name)
and some other program:
# hi-all.sys
(hello-worlder name: "Maria")
This seems straightforward, running hi-all
will print "Maria". That makes
sense, and the program itself has no free variables so it takes no flags. We
might wonder now if the --help
flag should be here implicitly, however I don't
see how that is really logical, since to find out some info about a function,
you don't usually pass it a :help
symbol, but rather pass that function itself
to some describe/help mechanism.
The other two points I'd like to make here are the fact that I absolutely might have as well just called
hello-worlder --name "Maria"
this should illustrate that there isn't really a difference between a function and a program, and that's one of my main points here. Next if I would have called only
(hello-worlder)
in my hi-all.sys
program, a question is raised whether it should error out, or
simply be a script with a mandatory --name
flag.
I'd vote for a compromise since we don't want a forgotten parameter to suddenly
pollute our command-line, I'd prefer an error unless I explicitly want to
parameterise on those values, and that could be done with any kind of arbitrary
syntax, for example placing my favourite &
symbol just before the called
function:
(&hello-worlder)
> Propagates the `name` parameter
(hello-worlder)
> Error: mandatory parameter `name` is missing
This of course implies non-mandatory parameters which are those that have some default value.
Would also be nice to have the Nix feature of initializing via any number of combinations of variables:
# hello.sys
first_name: String
last_name: String
full_name = "${first_name} ${last_name}"
(print full_name)
Then you could call it two valid ways:
hello --first-name Mike --last-name Atlas
hello --full-name "Mike Atlas"
hello --first-name Mike
> Error: full_name not specified (last_name missing to use default value)
The next question is what If I only wanted to access some config file from multiple places... would be nice to have one point of definition which is then usable in other places.
# user_info.sys
name: String
pass: String
And then be able to do:
(print user_info.name)
This would qualify my function/program (I need a name for this), to use the
user_info.sys
variables so they may be specified as inputs.
Help should probably have two modes of operation, one for direct parameters, and another to show all those SSL_CERT and PROXY settings that are usually not what I'm looking for. This also relates to the previous syntax, since some inputs might have colliding names, so being able to qualify them is useful:
foobar --ssl.cert foo --cert bar
However, what if multiple people actually name their functions the same... I do not have an answer for that now to be completely honest.
There's a decent question of what exactly the way to store and divide these up is. Do we keep them in files? I quite like the idea of going full binary and tracked references like Unison, this would allow us to construct a pretty nice graph of input nodes, functions and outputs nodes... transferrable files and associating variables to functions like this will probably be more hackable and easier to debug.
I'd also very much like for these to be callable from other language but that is probably pure wishful thinking.