Dinner with Stroustrup – Takeaways

Recently, I had the pleasure of having dinner with Bjarne Stroustrup, the creator of the C++ programming language, in Mountain View, CA. I talked to him about JS++, and here are a few takeaways (no pun intended):

Every industry is full of buzzwords; JavaScript is no exception. In order to get mainstream acceptance, JavaScript thought leaders maintained that JavaScript does support object-oriented programming – through prototypes. This is true; technically, JavaScript does support the pillars of OOP: inheritance, abstraction, encapsulation, and polymorphism. Historically, the problem with JavaScript isn’t the computer science concept of prototypical inheritance versus class-based inheritance; it’s the implementation of prototypes in JavaScript that result in spaghetti code.

Instead, Bjarne suggests: how does it benefit you? How does prototypical inheritance benefit you over classes? You don’t get SOLID, you don’t get custom types, etc. For instance, you’d have to really stretch the imagination to claim JavaScript supports the Liskov Substitution Principle, and some possible implementations for SOLID principles in JavaScript would – once again – result in spaghetti code. Don’t listen to “thought leaders” who have been yelling for years that prototypical inheritance is, in fact, superior to class-based inheritance (usually built on very weak arguments like “expressiveness”). Think critically. How does it benefit you? Does it make you more productive? (Certainly, spaghetti code can’t make you more productive.)

Furthermore, there is this constant re-invention of the wheel, such as trying to fit classic design patterns and paradigms into prototypes; this results in regurgitation after regurgitation of the Gang of Four Design Patterns book, and, oftentimes, these books are error-ridden and the authors do not have the depth of understanding of the design patterns in question to be writing a book about them. What’s wrong with classes and benefiting from all of the knowledge and intellectual capital that has been built up over the years for class-based OOP? The Gang of Four Design Patterns book is widely regarded as one of the classic texts on computer science and software engineering. Again, how does it disadvantage you and your work if you use classes rather than prototypes? Don’t listen to doomsday scenarios. Tune out the fearmongering. The truth is, classes have been used for decades in mission-critical scenarios like banking, telecommunications, aerospace, and rocketry.

As Bjarne suggests: what is your problem, and how can OOP or classes/prototypes solve them? And to the purists and zealots, what did he have to say? I quote: “Are you a Nazi?!” There are always going to be a crowd of people that will tell you that prototypes are the only way, that classes are bad, and only prototypes are the light. So I want to end this with: would you listen to a Nazi?

With that said, JS++ – by its very nature – is multi-paradigm like C++; it supports both prototypical inheritance and class-based inheritance.

Design Notes: Why Math.floor() does not return ‘int’

This is a commonly asked question. If Math.floor() and Math.ceil() will always return a whole number, why does it return double and not another integer type that represents only whole numbers like int or long? In Java, C#, and JS++, you’ll usually see a method signature as follows:

public static double floor(double x);

In actual usage, we may see scenarios such as:

int x = (int)Math.floor(10.5);

Hardly pretty. Why was it designed this way? Why couldn’t we just overload Math.floor() to return a different type based on whether we received an int, long, double, etc. argument?

To understand this, we must first understand that Math.floor() can take negative numbers as an argument. For example, Math.floor(-2.5) will return -3. Therefore, if we round down beyond the lowest 32-bit signed integer value (-2,147,483,648), we will no longer be within the range of an int (likewise for long). On the other end of the spectrum, we have Math.ceil(). If we round up beyond the highest 32-bit signed integer value (2,147,483,647), we will no longer be within the range of an int (and, again, likewise for long). However, a double (IEEE 754 double floating-point type) will fit both an int and long.

… But you might still be wondering whether or not we can still achieve this correctly through overloading (combined with wrapping or runtime exceptions for overflows)? Let’s assume we did. Math.floor() for an int when we receive an int, long when receive a long, etc. Look at this signature for a second; what’s wrong with it?

public static int floor(int x);

As you can see, this would defeat the purpose of Math.floor and Math.ceil. Why call Math.floor() on an int to receive the same number back?

You’re not going to have a decimal number to floor() or ceil() with int, long, etc. If we just make all the overloads accept a double argument, can’t we just return a different type? Sadly, no; it would be ambiguous, and it’s impossible to know whether we should return an int, long, etc. if the argument types were the same. Observe:

1
2
3
4
5
public static int floor(double x) { ... }
public static long floor(double x) { ... }
 
double x = 1;
floor(x); // do we return an int or long here?

Therefore, despite its inelegance, Math.floor() and Math.ceil() must return a double.