OOP via FP : functional nature of classes and objects
Tags: functional, lisp, ruby, oop
Published: 2024-02-07 22:31:45

## Topic for today
Today I would like to tell you, why such **OOP** concepts as **classes** and **objects** are just particular cases of **functions**, using examples of code in **Ruby** and in my own language, **Jena**.
Why **Ruby**? Despite that it is an object-oriented language, it also provides a **good foundation for functional approaches**. In that, I hope, my article will convince you, though it is a secondary point today.

## Jena references
If you are not familiar with **Jena**, you may read dedicated [article about this language](https://dev.to/taqmuraz/jena-one-more-programming-language-1llc).
If you want to try **Jena**, you are welcome to visit its [github repository](https://github.com/Taqmuraz/JenaLang).

## Object as a table of functions

Let us watch on an example of a class declaration in Ruby :
```ruby
class Human
  def walk
    puts "walking!"
  end
  
  def stand
    puts "standing!"
  end
end

h = Human.new()
h.walk
h.stand
```
Class is a popular idea, that has wide spread in modern languages, such as **Python**, **Java**, **C#**, **C++**.

What exactly do we see here?
Class `Human` seem to be a function, that creates objects.
But, also, object `h` here has two functions, and we may call them by their names.

May we try to implement the same behaviour, using only functions? Let us try :

```ruby
def Human
  return {
    :walk => -> do puts "walking!" end,
    :stand => -> do puts "standing!" end,
  }
end

h = Human()
h[:walk].call
h[:stand].call
```
I feel important to explain, what I am doing here. Function `Human` creates a hash-map, where symbols are associated with 
anonymous functions. Yes, `:walk` and `:stand` are symbols, it is a part of **Ruby** syntax, very uncommon in other languages.
As you may see, I chose **Ruby** for a reason. This language has one thing in common with **Jena** -- symbol literals.

## Honesty and clarity
More honest implementation of an object through a function would be this one :
```ruby
def Human
  map = {
    :walk => -> do puts "walking!" end,
    :stand => -> do puts "standing!" end,
  }
  return ->key do map[key] end
end

h = Human()
h.call(:walk).call
h.call(:stand).call
```
Now we are not using a dedicated syntax, **hiding object implementation** behind a function. You may say, that `Human` class code does look better, and code with functions is verbose and complicated. It is true, because syntax of **Ruby** (and most of other object-oriented languages) is **designed to make use of classes and objects easy**, sacrificing for that ease and clarity of functions.

Let me demonstrate the same behaviour, implemented in **Jena** :
```json
Human = () -> {
  .walk:() -> println "walking!",
  .stand:() -> println "standing!",
} =>
h = Human() => [
  h.walk(),
  h.stand(),
]
```
This code does **exactly** the same thing that the last **Ruby** code does : creates a `Human` function, that returns table of functions, calls it, storing result as `h` and, after that, calls `walk` and `stand` functions, taking them from table, using `.walk` and `.stand` symbols as keys.

## Mutable state
You may say, that objects have a mutable state, and, sometimes, it may be very useful. Methods may change attributes of an object, but may functions do the same?
Short answer is yes. Let us write some **Ruby** code
```ruby
class Human
  @x
  
  def initialize
    @x = 0
  end
  
  def moveLeft
    @x -= 1
  end
  
  def moveRight
    @x += 1
  end
  
  def status
    puts "x = #{@x}"
  end
end

h = Human.new()
h.moveLeft()
h.moveRight()
h.moveRight()
h.status()
```
How would look the same code in our approach, where object is a function?
```ruby
def Human
  x = 0
  map = {
    :walkLeft => -> do x -= 1 end,
    :walkRight => -> do x += 1 end,
    :status => -> do puts "x = #{x}" end,
  }
  -> key do map[key] end
end

h = Human()
h.call(:walkLeft).call
h.call(:walkRight).call
h.call(:walkRight).call
h.call(:status).call
```
And, in **Jena** it would be implemented next way :
```json
Human = () -> x = box(0) => {
  .walkLeft:() -> x.apply(-1),
  .walkRight:() -> x.apply 1,
  .status:() -> print ("x = " + (x.get)),
} =>
h = Human() => [
  h.walkLeft(),
  h.walkRight(),
  h.walkRight(),
  h.status(),
]
```
Dynamic languages, such as **Ruby**, provide us flexibility in control of program state, **we don't have to explicitly allocate memory** for a mutable state, **local variables already do present a state**.

## Performance
Our function-based objects have one serious flaw : low performance. We are building a functions table **each time we create a new object**, can we optimize that? Yes, of course we can, all we need is to **separate an object state from functions table** :
```ruby
$table = {
  :walkLeft => -> obj do obj[:x] -= 1 end,
  :walkRight => -> obj do obj[:x] += 1 end,
  :status => -> obj do puts "x = #{obj[:x]}" end,
}
def Human
  state = { :x => 0 }
  -> key do
    -> do
      $table[key].call(state)
    end
  end
end

h = Human()
h.call(:walkLeft).call
h.call(:walkRight).call
h.call(:walkRight).call
h.call(:status).call
```
And **Jena** :
```json
Human = table = {
  .walkLeft: obj -> obj.x.apply(-1),
  .walkRight: obj -> obj.x.apply 1,
  .status: obj -> print ("x = " + (obj.x.get)),
}
=> state = { .x:(box 0) }
=> () -> key -> () -> table key state =>
h = Human() => [
  h.walkLeft(),
  h.walkRight(),
  h.walkRight(),
  h.status(),
]
```
Looks overloaded? I agree. But, we may simplify that. Let us create a **class factory function**, so we may distract from building table and state functions each time we want to create a class :
```json
Class = table ->
  constructor ->
  args -> state = constructor args =>
    key -> arg -> table key args state arg =>

Human = Class {
  .walkLeft: () -> obj -> () -> obj.x.apply(-1),
  .walkRight: () -> obj -> () -> obj.x.apply 1,
  .status: () -> obj -> () -> println("x = " + (obj.x.get)),
} args -> { .x:(box (args.x)) }  =>

h = Human{.x:5} => [
  h.walkLeft(),
  h.walkRight(),
  h.walkRight(),
  h.status(),
]
```
As you see, now we even can pass constructor arguments to build our object, it is a **full complete object-oriented class**, implemented by **functions only**.

## Other reasons to choose functions over objects
For many of readers solution with classes looks more familiar and pleasant, but only because you already have experience using that solution.
**Functions are coming from a mathematical world**, their **abstraction and distraction from implementation details** are attractive indeed. Functions have simple and consistent concept behind, while objects are very specific and domain-oriented.
Finally, class in most of the object-oriented languages is a **separate syntax**, what brings more complexity and involves a **special logic for constructors, methods and attributes**.

That's all for today. **Thank you for reading, and please, share your thoughts in comments**.