Apply some coercion

Type coercion comes in three flavours according to intent, and languages should support distinguishing between these three flavours. Each means of doing type coercion should be designed with that intended use in mind. As a special case of the guideline that in a usability context, the broadest structural divisions should be between the most conceptually different objects, it follows that this division of intent should inform the syntax of type coercions at the largest scale.

The first type is when you don't even realise you're doing a coercion. Casting integers to real numbers, when information-preserving, is an instance of this. Doing bitwise operations on symbolic names for flags is another. The abstract operation of combining flags and the machine operation of bitwise and (or whatever) are isomorphic, in a hand-wavy sense. Yet another example is the invisible cast that is done when calling the method of a parent class on an instance of its subclass.

Sometimes you are doing a true coercion, in that you want to change the machine representation of the data, as in the int-to-real case. Sometimes the cast is entirely within the type system, as in the flags case. Sometimes it might be either, as in the method inheritance case. The user (by which I mean the programmer, who is a user of the language and compilation system) shouldn't need to know which.

The second type demands a bit more awareness from the user, as it involves changing not only the representation but the abstract data. Non–information-preserving numerical transforms, e.g. from real to integer, are an instance of this, as is parsing a number out of its string representation. Converting something to a string can be considered another: in Java, this can always be done by automatically inserting a call to the object's toString() method.

Really, this shouldn't be thought of as type coercion at all, but almost every language has some operation of this type accomplished by something that's syntactically a cast. Even C++'s operator type custom type conversions encourage the user to write casts that return something with a different meaning. In this case, the syntax of the coercion should be visible but not long-winded: Perl 6's single-character “boolification”, “stringification”, and “numification” operators are a good short-hand, though there aren't enough characters in Unicode to make it that short for every type.

The third type is the hard core of casting, when you know you're doing something out of the ordinary and just want the type-checker to get out of your way. Almost always in this case you don't want to change the machine representation of the data, just the type system's idea of what it means. C++ has the reinterpret_cast to set this operation apart from the others. In Java and C#, you have to achieve this sort of effect with reflection.

The usual use for such code is wherever you want to turn objects into byte streams and back: network protocols, object persistence, ORM, memory management, filesystems, character encoding conversion, &c. The other major use is when you are trying to to write code that abstracts across types in a language, or codebase, that doesn't support such polymorphism. Almost all uses of void * in C are for this purpose. Even modern statically-typed languages like Java and C#, where type-safety is crucial to their security and safety claims, have the object minimal type for writing code using subtype rather than parametric polymorphism. The difference here is that Java and C# use RTTI to ensure that objects can be cast to object and back but fail immediately and in a defined way (at run-time) if they have their types changed. That is, they provide a mechanism for defeating the compile-time type checker but not run-time type correctness, whereas C has no run-time type checking.

So, we have three broad divisions with which to classify coercion in terms of the user's intent. Now all we need is three syntactic formulae to represent them, and make it clear to the reader which is intended.