Ergonomica is a fork of Scheme-based, Lisp-like languages. It's not purely functional in that it allows for:
- global/local variable definitions
- commands that have side effects (on the filesystem)
However, ideally all commands will be generally written in a functional manner. It's syntax is that of S-expressions, with a few caveats:
(set x (+ 1 3 2)) # standard Lisp expression
set x (+ 1 3 2) # Ergonomica expression
In this example, the $
character is used to indicate variable substitution.
.: set f (lambda (x) x)
.: f 33
x
.: set f (lambda (x) $x)
.: f 33
33
Ergonomica has piping built into it's S-Expression syntax. These seperate commands and arguments within S-Expressions. All values that are piped are explicitly specified, with {}
syntax. This syntax is built around the concept of blocks being passed between items in a pipeline. The simplest example of a pipeline is simply passing all of the output of the previous command, like so
.: print 1 2 3 | first ${}
1
.: print 1 2 3 | rest ${}
(2, 3)
However, portions of these blocks may be specified. For example, if we wanted to print every other element, we could create a pipeline with a blocksize of two and always print the 2nd element of that array.
.: ls
a.txt
b.txt
c.txt
d.txt
.: ls | print ${1}
b.txt
d.txt
The number within the {}
indicates the index of the item being substituted from standard in.
Note that in this example, the blocksize was not explicitly specified. Ergonomica reads for the largest index and makes standard in big enough to contain that value. In this example, the block size was 2, resulting in the blocks looking roughly like the following:
[[a.txt, b.txt], [c.txt, d.txt]]
Then, filtering for our indices yields the values expected:
[a.txt, b.txt][1] -> b.txt
[c.txt, d.txt][1] -> d.txt
However, suppose you want a.txt
and c.txt
(i.e., not starting alternating with b.txt
). Specifying ${0}
would just print every element (a blocksize of one, i.e., a block for every element)
.: ls | print ${0}
a.txt
b.txt
c.txt
d.txt
You may specify the blocksize explicitly like so:
.: ls | print ${0/2} a.txt c.txt
And we have our desired result! {}
substitution may be done for an arbitrary number of substitutions, in place of regular arguments.
When Ergonomica does not find a command in its namespace, it then runs it using subprocess
. As a result, most normal commands should work exactly how you would expect---they may be used in expressions, used in Ergonomica pipelines, and everything else a normal command would do. However, there is an override for running commands using os.system
, which may be required for some interactive commands (such as less
). This override is a %
at the beginning of a commnad, like so:
%less example.html
Note
This prefix may also be used to force a command to be run by the system instead of Ergonomica (however full paths like /bin/bash
also work).
In Ergonomica, as with similar functional programming languages, the only statement in the language is the if/elif/else
statement. It is used to execute certain code when a certain condition satisfies (or doesn't satisfy) a given condition. For example, to detect whether a number is greater than five,
if (> $n 5) (print "It is greater than five!") else (print "It isn't greater than five...")
Or to test for a variety of different conditions, the elif
statement can be used to evalute a statement only if the previous condition wasn't true and the current condition is,
if (> $n 5) (print "It's greater than five.") elif (> $n 0) (print "Well at least it's positive.") else (print "Well shucks")
Note
These statements may have linebreaks in any location; for example, each elif
could be on a newline. This does not affect their behavior.
with (find file .*pyc) as python_files ( )
It also allows you to perform functions with side effects on the system.
with (rm /) as _ ( )