Philosophy behind Operon

Operon uses a dataflow-paradigm, that is quite different to object-oriented or functional programming. It allows to express the goal in a concise manner, in one expression. This allows for simplicity.

Operon's use of JSON-dataformat means that the data is as near as possible. There are no extra layers built on top of the data. I want to feel the data when programming transformations. Operon goes beyond JSON, supporting pure data-integration, as uninterpreted bytes.

The powerful mechanisms of modularity, component-system, first class function-support.and type-system allow for effective data querying, transformation and integration. These are actually the basis for any application, so is not used for only some niche purpose, but is applicable for very wide range of tasks.

To install Operon you first need to have Java JVM installed. Java 8 or newer is required.

Download the JDK13 from here:

Here are the installation instructions:

After this download the Operon binaries from here:

To run the query in command prompt, use the following: java -jar operon-0.5.0-SNAPSHOT.jar queryname.op

JSON is a concise format to describe data. Here's a short description of how to read JSON-notation:

Text (String): to tell that something is of text-format (known as "String"), you simple enclose the data inside double quotes. For example the following is valid JSON-string: "Hello!".

Numbers: the following are examples of the valid JSON-numbers: 1, 2.0, 3.1415, -4

Arrays: you can list other JSON-objects inside an array. Array is denoted by "[" and "]" -brackets. For example here's a list of numbers: [1, 2, 3]. Here's an another example, where we have a list of numbers and strings: [1, "two", 3, "four"]

Objects: JSON-objects are like dictionaries, where you look up an entry by a key. Here's an example: {"key1": "value for key1", "key2": "value for key 2"}. The keys are string-type, but the value may be of any JSON-type.

Boolean-types: true and false.

Null-type: null
First query


Let's look what is going on here, line by line:
1. From: this starts the From-statement. Each query has one. It tells from where the data is read.
2. json:123: in this case we use "input source" called "json", and assign value 123 directly for it.
3. Select: this starts the Select-statement. Each query has one. It tells what we want to output from the query.
4. $
: this means "root-value of the query". In this case the root value is 123, which was assigned for the json-input source.

Note that the white spaces e.g. in front of "json:123" are not required, but they make the query nicer to read, which is very important.
Another thing to note is that the keywords start with capital letter. This is not optional, but enforced by the language. It makes it nicer to read, which - as I sayd earlier, is very important.
Second query

We'll use the notion "#>" to express the output of the query. It is not part of the query itself.

    json:"hello world!"
Select $ => string:upperCase()


One of the ways to use functions in is shown in the above query. So you "forward" the data in for the function, using the "=>" -notation. You can pipe the functions together this way, making the query nice to read:

$ => string:upperCase() => substring(1, 6)



These are the function-categories available, currently with the following functions:
  • string
    • base64ToString, contains, endsWith, length, lowerCase, search, splitBy, startsWith, substring, toBase64, trim, upperCase
  • object
    • count, key, keys, value
  • array
    • avg, count, distinct, first, flatten, forall, foreach, get, last, max, min, reduce, sum, next, previous
  • date
    • add, now
  • math
    • abs, acos, asin, atan, ceil, cos, exp, floor, log, pow, round, sin, sqrt, tan
  • random
    • number
  • env
    • get
  • function
    • fullName, name, namespace
  • state
    • get, set
  • binary
    • base64ToBinary, binaryToBase64
  • core
    • boolean, number, string, pos, parent, root, getCarvedBytesById, type, mappableTo, fullyMappableTo
When in the query a function from one of the above categories is used, then the category-name must appear before the function name (this is not mandatory for some functions). E.g.

Select 0.567 => math:round()
#> 1.0

 This is actually known as "namespace" for the function. For the core-functions the namespace is statically bound.

The namespace "core" is at the root of each namespace. We could say, for example: core:math:round(), which is the same as math:round.
Further topics to discuss (content not available yet):
  • Expressions
  • Conditions
  • Filtering
  • Ranges
  • Comparisons
  • Splicings
  • Function references
  • Lambda functions
  • Function parameters
  • Integration calls
  • Type-system
  • Map-operator
  • Let-statements
  • Update-value
  • Bind-value
  • Object access
  • Object deepscanning
  • Error handling
  • Import -statements
  • Compiling code
If you found the above short introduction blocks interesting, then you'd be glad to hear that there are tons of interesting material coming, as soon as I just can put them together. If you haven't yet, then please sign up for the newsletter and you'll get to know when new content is available!
© 2020