This is a mobile version, full one is here.
24 November 2020
Objects Without Methods
What do you think an object is in OOP? No matter what language you are programming with, you will most probably agree with Bruce Eckel, the author of Thinking in Java, who said that “each object has a state and operations that you can ask it to perform,” or Benjamin Evans, the author of Java in a Nutshell, who claimed that it is “a collection of data fields that hold values and methods that operate on those values.” However, hold on… What if I told you that an object may have no “operations” and still be a perfect “equivalent of the quanta from which the universe is constructed,” as David West suggested in his great book Object Thinking?
In EO, our experimental programming language, we made an attempt to re-define OOP and its objects. There are two types of things in EO: atoms and objects. An atom is the lowest level language primitive, which can’t be expressed by other atoms. For example, an arithmetic addition of two other objects is an atom (stay with me, this is EO syntax, you will get used to it):
add 5 y > x
In a more traditional Java-like infix notation this code would look like this:
x = add(5, y)
The atom is
add and its two specific
y. This statement creates a new atom, using
the existing one and specifying its arguments. The name of the new atom being
x. Once we ask this newly created atom to do anything,
it gets what’s in
5, and starts behaving
like a summary of them. Until then, it stays quiet.
EO is a declarative language.
Atoms are provided by the EO runtime. For example,
div are for arithmetic operations;
for are for forking and iterating;
or are for logical operations, and so on.
Atoms may resemble low-level functions with arguments.
However, they don’t calculate results immediately, but only when needed.
add(5, file) won’t lead to reading the content
of the file and adding 5 to it immediately. Only when the
created atom is dealt with will the file reading happen.
Next, on top of these atoms, objects can be created by a programmer. For example, this is an object that represents a circle:
[r] > circle mul 2 3.14 r > perimeter mul 3.14 r r > area
The first line creates an “abstract” object named
circle. It is abstract,
because one of its attributes
r is “free”. It’s not specified
in this object and that’s why the object can’t be used as is, it has
to be copied with
r specified. For example, this is the circle
with the radius 30:
circle 30 > c
circle has three attributes. The first one is
r, which is free.
The other two are
area. They are “bounded,” since their
atoms are already defined:
mul in both cases. To get the area of the
c we do this:
c.area > a
It looks like a method call, but it’s not. We don’t call a method, we just
area object from the object
c. It’s not created for us
at the moment we do
c.area! It has already been there sitting and waiting
for us to take it. It was created right when the object
c was built.
This is the difference between methods in Java and attributes in EO. In Java, every method is a procedure to be executed as soon as it’s called. This method calling (or message sending, according to early OOP adepts) mechanism was inherited from C functions, which itself we inherited from ALGOL procedures, I believe. EO does it differently. There is no method calling. It just takes attributes out of objects and gives them to other objects, until control is passed to them and it gets down to the level of atoms.
In the example above, the object
a is not a calculated number.
It’s an atom
mul that encapsulates
30 (the radius). The
result of the calculation is not yet known. If we don’t do anything
a, the CPU will never do the calculation. However, if we decide
to, say, print the number to the console, the calculation will happen:
stdout sprintf "Radius is %d, Area is %d" r a
Here, the atom
sprintf constructs the string, which encapsulates
three attributes: the text,
a. By the way,
it’s possible to use either vertical or horizontal notation
for constructing objects. The code above may be written like this:
stdout (sprintf "Radius is %d, Area is %d" r a)
stdout encapsulates the string constructed by
and stays quiet. It doesn’t print anything! Only when someone
at some point tries to “touch” this object, taking one of
its attributes out, the atom
stdout will drop the line to the
There are no attributes in
mul, and most
other atoms, except one: 𝜑.
Any object or atom has this specific attribute, also known as
the “body” of an object. Once someone attempts to touch
the console will see the string.
Thus, we have objects, but we don’t have methods. There are only attributes representing other objects.