Dynamic comparison instead of dynamic typing

There had been a long-running debate among developers about the relative merits of of static or dynamic, weak or strong typing.

Static typists will argue about compiler optimization, type safety, etc.  Dynamic typists will talk about flexibility and cleaner code.

There have been several attempts to find a common ground using type coercion, “duck” typing, implicit type casting, optional typing, etc.

Strong typists argue for catching errors early, preventing subtle defects, etc.  Weak typists just want to get work done and think that most of the time your just dealing with numbers or strings.

I’m in the weak/static camp, sortof.  I see the advantages of strong typing (in theory), and the practical advantages of dynamic typing (in practice).

But the biggest advantages I see of static typing is discovery (in your IDE) and of weak typing is readability.  In other words, they make my job as a developer easier.  Forget type safety, correctness, and even simplicity and flexibility.

However, weak typing is best demonized by two examples… void * in C and everything in PHP & Javascript.

Static typing is easily attacked by the amount of successful code written in languages like Perl, PHP, Python, and Ruby.

It doesn’t have to be this way though.  We can all get along.  I agree that type coercion and duck typing can lead to some very subtle bugs.  And I agree that the verbosity required of static typing can be a pain and a real flow killer.

What I’m proposing is to forbid type coercion, and replace it with sane type comparison.

The simplest type comparison is 1==true or 0==false.

Things can get trickier (and more ambiguous) with null==false or “true”==true.

And what about empty strings, converting numbers to strings, or strings to numbers.

In languages like Perl, an array returns it’s size.  Should an array of size zero return null?

Also:

  • What about numeric values such as Javascript’s NaN (not a number)?
  • What about comparing integers and floating point numbers?
  • What about objects?
  • What about object hierarchies?
  • What about equivalence vs identicalness (identicality vs identity)?
  • What about comparing references?

Obviously it’s a tricky rabbit hole, and some decisions need to be made.  And I’m prepared to make them.

First of all, we don’t have to live with type coercion — except when we make comparisons or want to explicitly cast from one type to another.

parentheses have a type comparison operator

if (foo == null) should be reduce to if (foo)

This means that you’ll need temporary objects, but hey, we have lots of memory, right.  For most types, though, you can have one instance of a conversion tree.  Objects can override the comparison and conversion functions if they want to.

By having the type comparison in the parentheses, you can also invoke it with a cast

foo = (int) foo

Objects can have a comparison operator — the default object comparison operator returns its type.  Types return a string of the type name.

== is for comparison, === is for identity (yes, PHP got this right)

I’m not sure what to do about string comparison.  I’m loath to admit that Java got it right that all strings are immutable and use a single hash table and GUIDs.

But what if all numbers were just an immutable table.  You could have one for integer values and one for decimals?

Anyway, the point I’m getting at is the general principal that you should always be able to compare types implicitly, and cast them explicitly.  By allowing these two things, you gain most of the simplicity & readability benefits of dynamic typing, and still retain most of the safety and discovery of static typing.  And you avoid then otherwise necessity of weak typing in many cases.

Someone buy this guy a TLDR;