EO (stands for Elegant Objects or ISO 639-1 code of Esperanto) is an object-oriented programming language based on π-calculus. We're aware of popular semi-OOP languages and we don't think they are good enough, including: Java, Ruby, C++, Smalltalk, Python, PHP, C#. All of them have something we don't tolerate:
- types (why?)
- static/class methods or attributes (why?)
- classes (why?)
- implementation inheritance (why?)
- mutability (why? and why not?)
- NULL (why?)
- global scope (why?)
- type casting (why?)
- reflection (why?)
- scalar types and data primitives
- annotations (why?)
- operators
- traits and mixins (why?)
- flow control statements (
for
,while
,if
, etc)
Then, install eoc:
npm install -g [email protected]
Then, start with a simple EO program in the app.eo
file:
# Just prints hello.
[args] > app
QQ.io.stdout > @
"Hello, world!\n"
Compile it like this (may take up to a minute or so):
eoc --easy link
Then, run it:
eoc --easy --alone dataize app
You should see "Hello, world!" printed.
In the example above, we create a new abstract object
named app
, which has got a single attribute named @
. The object
attached to the attribute @
is a copy of the object stdout
with
a single argument "Hello, world!"
. The object
stdout
is also abstract.
It can't be used directly, a copy of it has to be created,
with a few requirement arguments provided.
This is how a copy of the object stdout
is made:
QQ.io.stdout
"Hello, world!\n"
The indentation in EO is important, just like in Python. There must be two spaces in front of the line in order to go to the deeper level of nesting. This code can also be written in a "horizontal" notation:
QQ.io.stdout "Hello, world!"
Moreover, it's possible to use brackets in order to group arguments and avoid
ambiguity. For example, instead of using a plain string "Hello, world!"
we may want to create a copy of the object stdout
with a more complex
argument: a copy of the object sprintf
:
# Says hello to Jeff.
[] > app
QQ.io.stdout > @
QQ.txt.sprintf
"Hello, %s!"
* "Jeffrey"
Here, the object sprintf
is also abstract.
It is being copied with two arguments: "Hello, %s!"
and "Jeffrey"
.
This program can be written using horizontal notation:
+alias org.eolang.io.stdout
+alias org.eolang.txt.sprintf
# Also says hello to Jeff.
[] > app
stdout (sprintf "Hello, %s!" (* "Jeffrey")) > @
The special attribute @
denotes an object that is being
decorated.
In this example, the object app
decorates the copy of the
object stdout
and through this starts to behave like
the object stdout
: all attributes of stdout
become the
attributes of the app
. The object app
may have its own
attributes. For example, it's possible to define a new abstract object
inside app
and use it to build the output string:
# Says hello to Jeff.
[] > app
QQ.io.stdout (msg "Jeffrey") > @
[name] > msg
QQ.txt.sprintf "Hello, %s!" (* name) > @
Now, the object app
has two "bound" attributes: @
and msg
. The attribute
msg
has an abstract object attached to it, with a single "free" attribute
name
.
This is how you iterate:
# Multiplication table.
[args] > app
malloc.for > @
0
[x] >>
seq > @
*
x.put 2
while
x.as-number.lt 6 > [i] >>
[i] >>
seq > @
*
QQ.io.stdout
QQ.txt.sprintf
"%d x %d = %d\n"
*
^.x
^.x
^.x.as-number.times ^.x
^.x.put
^.x.as-number.plus 1
true
This code will print this:
2 x 2 = 4
3 x 3 = 9
4 x 4 = 16
5 x 5 = 25
Got the idea?
This is our EBNF of EO language:
This is the EBNF of π-calculus:
The PNG images were auto-generated. It's better to use ebnf/Eo.svg and ebnf/Phi.svg.
Join our Telegram group.
Watch video about EOLANG basics.
Read our blog, especially the section with recently published papers.
Learn XMIR, a dialect of XML, which we use to represent EO program: XSD and spec.
See the full collection of canonical objects: objectionary.
Play with more examples in the sandbox.
Read more about integration with Maven.
This is how many milliseconds were spent on different XSL stylesheets
during the execution of mvn install
of the eo-runtime
module:
to-java.xsl 92371 43.20%
classes.xsl 60524 28.30%
set-locators.xsl 16585 7.76%
set-original-names.xsl 10794 5.05%
attrs.xsl 8894 4.16%
data.xsl 8148 3.81%
anonymous-to-nested.xsl 5568 2.60%
package.xsl 5535 2.59%
tests.xsl 5417 2.53%
The results were calculated in this GHA job on 2025-06-05 at 13:05, on Linux with 4 CPUs. The total is 213836 milliseconds. We show only the first 16 most expensive XSL stylesheets.
You can run this benchmark locally with the following commands.
First, to generate the measures.csv
file:
mvn clean install --errors --batch-mode -Deo.xslMeasuresFile=measures.csv
Then, to generate the report:
awk -F ',' '{ a[$1]+=$2; s+=$2; } END { for (k in a) \
printf("%s.xsl\t%d\t%0.2f%%\n", k, a[k], 100 * a[k]/s)}' \
eo-runtime/measures.csv | sort -g -k 2 | tail -r | column -t | head "-16"
Fork repository, make changes, then send us a pull request.
We will review your changes and apply them to the master
branch shortly,
provided they don't violate our quality standards.
To avoid frustration, before sending us your pull request
please run full Maven build:
mvn clean install -Pqulice
You will need Maven 3.3+ and Java 11+ installed.
Also, if you have xcop installed, make sure it is version 0.8.0
+.
We are using the YourKit Java Profiler to enhance the performance of EO components: