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 arguments are 5 and y. This statement creates a new atom, using the existing one and specifying its arguments. The name of the new atom being created is x. Once we ask this newly created atom to do anything, it gets whatâs in y, adds 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, add, sub, mul, and div are for arithmetic operations; if and for are for forking and iterating; less, and, eq, 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. Saying 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 c with the radius 30:
circle 30 > c
The object circle has three attributes. The first one is r, which is free. The other two are perimeter and area. They are âbounded,â since their atoms are already defined: mul in both cases. To get the area of the circle 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 take an 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 3.14 and 30 (the radius). The result of the calculation is not yet known. If we donât do anything with 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, r, and 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)
The atom stdout encapsulates the string constructed by sprintf 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 console.
There are no attributes in stdout, sprintf, 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 stdout.đ, the console will see the string.
Thus, we have objects, but we donât have methods. There are only attributes representing other objects.
