Skip to content

Latest commit

 

History

History
138 lines (84 loc) · 4.61 KB

syntax.rst

File metadata and controls

138 lines (84 loc) · 4.61 KB

Introduction

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:

No outer parentheses

(set x (+ 1 3 2)) # standard Lisp expression

set x (+ 1 3 2)   # Ergonomica expression

Any strings after the operation in S-Expressions interpreted as strings

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

Pipelines

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.

System Commands

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).

if/elif/else statements

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 statement

with (find file .*pyc) as python_files (

)

It also allows you to perform functions with side effects on the system.

with (rm /) as _ (

)