Tuesday, August 16, 2011

Tiny-Type Language Support

Tiny-Type Language Support

Tiny-Types are types in object-oriented programming that contain very little data, but still have the benefits of objects. The typical example is currency. Tiny-types are underused which in part is due to poor language support. Although some of these shortcomings can be solved by code generation, it would be beneficial if such friction weren't necessary (although Scala case classes take care of some of these concerns). There are several features that are missing in mainstream languages that would make using tiny-types easier.

Built-in hash code

Many IDEs provide support to generate hash codes automatically. However, this does not stop them from getting out of sync, as they are not automatically regenerated when the types or number of fields change. This can be provided in an IDE, but it would be easier to just provide this mechanism in the language. Say as an alternative to a class, one could use the keyword value that would automatically provide the hash code for you given the fields in the type.

Built-in equality

Equality is another method that can be generated by the IDE but can become stale when the types or number of fields change. This can be implemented by the same mechanism as with hash codes. Additionally, there should only be one method/operator that does equality. In Java there is .equals() or operator== depending on whether or not the type is a class or primitive. In C#, you have to implement both if you want proper functionality as operators are overloadable. The in-fix notation, which is used by operator==, is more habituated due to the way most of us learned math. Therefore, the method .equals() should be eliminated, leaving one place for both primitives (values) and classes to define equality.

Built-in JSON/binary serialization

Tiny-types are convenient as messages where message passing between processes or threads are used. While serialization is not necessary between threads, it is essential for communication between processes. Both JSON and some form of standardized language-independent binary serialization (perhaps Message Pack, Thrift, or gobs (but language-independent?) should be generated for value types by default.

toStr() defaults to JSON

String methods are another facility that can be generated by an IDE or by code generation, but again this should be unnecessary for value types. The default for toStr() method should produce JSON. As with serialization, equality, and hash codes, toStr() should be overrideable.

Immutable

Object level immutability is sorely lacking from many mainstream object-oriented languages, with the exception of C++. Value types should be immutable, allowing for guarantees with intra-process message passing. Immutability is also useful for hashing.

Operator overloading

Operator overloading is very important for tiny-types, particularly for mathematical operations. Anyone who has ever used the terrible syntax required by BigDecimals in Java can attest to how nice it would be to have operator overloading. One of my main complaints about Go is the lack of operator overloading. I understand why it was left out, but I believe the pros outweigh the cons. C# strikes a nice balance here by allowing the overloading of mathematical operators but not assignment or arbitrary operators.

Tiny-type support is lacking in most modern mainstream object-oriented languages. This is unfortunate as it takes away from the full benefits of object-orientation and would be easy to remedy by language designers.