Learn the true polymorphism
Computer Scientist. Researching on Artificial Intelligence and working as a Software Engineer. Cuban based in Spain.
Search for a command to run...
Computer Scientist. Researching on Artificial Intelligence and working as a Software Engineer. Cuban based in Spain.
Hey, nice article! Came from reddit where saw some bashing. I'll read the rest of the series. I remember seeing OO on CLOS some time ago and thinking it was hacky. Now I see the true power better. Thanks a lot
Thanks! Helping others is what makes me write these articles. I'm glad you had enjoyed the series so far. Stay tuned!
In this series, I present a lot of Lisp cool features. This series is growing constantly because there is a lot to talk about this topic.
What if I tell you that you can always have the language that better fits your problem? We are always implementing design patterns and abstractions to adapt our programming language to the domain of the problem. We create the classes Store, Product, ...
A series on how to predict the future

A series on how to predict the future

One of the greatest discoveries of all times explained in a bunch of simple words
The field of Predictive Analytics is everywhere these days. We can hear about it in several and different areas like medicine, businesses, industries, and so on. But what exactly Predictive Analytics is? How can some algorithms predict the future, an...
Greedy algorithms try to find the optimal solution by taking the best available choice at every step. For example, you can greedily approach your life. You can always take the path that maximizes your happiness today. But that doesn't mean you'll be...
Polymorphism is the ability of an object to take on many forms. It is an everyday word in Object-Oriented Programming (OOP). We have classes that inherit from other classes. We can treat an instance of a child class as an instance of the parent class, but it will behave differently.
Common OOP languages have a very limited version of polymorphism. In this post, I'm going to talk about a wider version of polymorphism that is included in Lisp.
Let's see first what can be done with the polymorphism we commonly use.
As a simple example, we can have a class called Shape with a method called Area. We also can have other classes called Triangle, Rectangle, Circle, etc. Those classes inherit from Shape, and each one provides its own implementation of the Area method.
We can make a list that only contains shape instances and treats every element as an instance of the Shape class. But when we do element.Area() we get different implementations every time. No matter that we treat every element as a Shape instance, every one of them behaves as a Triangle, a Circle, or a Rectangle according to its class.
That's the kind of polymorphism you might use in your favorite OOP language. But what if I tell you that's a very limited kind of polymorphism?
In the previous example, we had a method inside a class that got overridden by every child class. That was good because we wanted to have different implementations of the Area method for every shape.
Let's think about another example. Now we have a class Drum, and also let's create the class Stick. Where do you include the Play method? Inside the Drum class? Inside the Stick class?
If you choose to include it inside Drum, then you can have different implementations of Play for every different drum you create. But what happens when you have a different stick? You can't have polymorphism with respect to the Stick instance! Exactly the opposite happens if you decide to include the method inside the Stick class: you'll have polymorphism on the Stick instances but not on the drums.
Where's your polymorphism now?!
Let's think about this issue. What happens when you do classInstance.ClassMethod(<args>)?
We can say we are invoking the ClassMethod inside the classInstance. But let's change the previous code a little bit:
ClassMethod(classInstance, <args>)
Now we see things slightly different. We are invoking the ClassMethod passing the classInstance as the first argument.
Maybe this is familiar to you. For example, in Python, you can invoke class methods using both ways interchangeably. Both of them are equivalent.
Using the second way, we can achieve different ClassMethod behavior by changing the classInstance argument. That's equivalent to polymorphism we use every day. That's called polymorphism in the first argument.
Let's return to our "drum and stick" example. The solution would be having something like this:
Play(drumInstance, stickInstance, <args>)
Now we can have different behavior for every Drum-Stick combination. Nice!
But that's not a natural solution in many programming languages. Usually, every method has the "special" first parameter reserved for the instance of the class where it is defined. Hence, we can't have many "special" parameters representing many different instances of different classes. Even more, many OOP languages don't allow you to define methods outside of a class. So yes, you probably have been using a very limited version of polymorphism during your coding life.
Let's see what Lisp has to say!
Lisp is a very old programming language. It's so old that there was no OOP when it was created. But in the '80s a new update of the language came up with the Common Lisp Object System (CLOS), And then, Lisp became an OOP language.
As a matter of fact, CLOS is implemented in Lisp itself. There are a lot of great things about Lisp. I will definitely write about more of those things shortly.
There are no class methods in Lisp. Methods don't belong to the class. You have classes with properties and methods that can receive instances of those classes as arguments. It's the solution we talked about! That's how Lisp provides us with polymorphism on multiple arguments.
Of course, you can solve all kinds of problems with the "regular" polymorphism. You also can solve all kinds of problems without OOP at all! You can think about solving the Drum-Stick problem with a design pattern or some abstraction. But polymorphism in multiple arguments is explicit and simple.
Lisp's CLOS has a lot of more interesting features. This was the first one that really impressed me. Also was the first one I exploited a lot for solving some problems. Talking about other features of CLOS requires some prior knowledge of the language, but I plan to write about topics that don't demand such knowledge. Like this one!
Let's summarize what we have been talking about.
Polymorphism is a cool feature in OOP. It is the ability of classes to behave differently, in different scenarios. But the kind of polymorphism that is present in popular OOP languages is limited.
Yes, there are different types of polymorphisms. We commonly use polymorphism on the first argument, but we can have polymorphism on multiple arguments. To achieve that, we need to separate methods from classes.
Lisp is a multiparadigm (Object-Oriented included) programming language. In Lisp, methods are created outside classes, and we can have polymorphism on multiple arguments.
Using this more general polymorphism you can get rid of some abstractions and design patterns that maybe you have been using to solve problems similar to the Drum-Stick one.
There are a lot of other features about Lisp that are mind-blowing. It really changes the way you think about programming. I plan to write about some of those features with a focus on the change of paradigm instead of the language.
But I recommend you to take a look at Lisp, and to experience those features and different ways of thinking by yourself.
If you liked the post let me know. You can leave a comment with whatever you want to say. You can also follow me on Twitter for debates and thoughts about related topics.