I read this article about programming a tic-tac-toe game in Nix. The concept is interesting, but writing contents to a file as input and outputing to realized derivations is far from desired. However, I noticed that Lix allows you to read input from stdin by using builtins.readFile /dev/stdin (while the vanilla Nix does not) and that builtins.trace can output things visible in the console, so I can write a decent interactive program that has input and output and does not involve derivations at all. Try this simple demo:
#!/usr/bin/env nix-shell
#!nix-shell --pure -i nix-instantiate -p lix
let
do = statements:
_: builtins.foldl' (_: statement: _ // statement _ _) _ statements;
assign = attr: value:
_: _ // { ${attr} = value; };
print = message:
_: builtins.trace message _;
ifElse = condition: ifTrue: ifFalse:
_: if condition _ then ifTrue _ else ifFalse _;
while = condition: body:
ifElse condition (_: do [ body (while condition body) ]) (_: do [ ]);
main = statement: builtins.seq (statement { } { }) "";
in
main (_: do [
(_: assign "number" 0)
(_: print "Current value: ${toString _.number}")
(_: print "Input an operation (+, -, *, /) followed by a number, press Enter, and then press Ctrl+D")
(_: assign "input" (builtins.readFile /dev/stdin))
(while (_: _.input != "") (_: do [
(_: assign "match" (builtins.match "^([-+*/]) *([0-9]+)\n$" _.input))
(ifElse (_: _.match == null) (_: do [
(_: print "Invalid input")
]) (_: do [
(_: assign "operator" (builtins.elemAt _.match 0))
(_: assign "operand" (builtins.fromJSON (builtins.elemAt _.match 1)))
(ifElse (_: _.operator == "+") (_: do [
(_: assign "number" (_.number + _.operand))
]) (_: do [
(ifElse (_: _.operator == "-") (_: do [
(_: assign "number" (_.number - _.operand))
]) (_: do [
(ifElse (_: _.operator == "*") (_: do [
(_: assign "number" (_.number * _.operand))
]) (_: do [
(ifElse (_: _.operator == "/") (_: do [
(_: assign "number" (_.number / _.operand))
]) (_: do [
]))
]))
]))
]))
]))
(_: print "Current value: ${toString _.number}")
(_: print "Input an operation (+, -, *, /) followed by a number, press Enter, and then press Ctrl+D")
(_: assign "input" (builtins.readFile /dev/stdin))
]))
(_: print "Goodbye!")
])