Selector namespaces
Object-oriented design lets us avoid a bunch of “if-elsif-else” lines of code and use polymorphism instead. Sometimes it is extremely helpful to be able add or replace methods in core classes like strings, numbers and arrays. Ruby has such ability, but sometimes it turns out to be a nightmare. One library may redefine some String method for its own purpose and completely fuck up things in another library. In reality, library needs to redefine String class in that library’s namespace only. Let’s examine the possible ways to achive this:
1. In a pure OO-language only thing we have is message sends. When we write “string.size” we pass a message “size” to an object referenced by the local variable “string”.
Suppose, we have a library doing some low-level byte manipulations which relies on byte count behind “size” method. On the other hand, our application would like to deal with character count (one Cyrillic character is encoded with 2 bytes in UTF-8).
We want to keep the string in a same class (“String”) and also use the very same selector “size” for the different methods. So, how do we determine which method to choose, when class String receives the message “size”? The solution is to keep a thread-local stack of namespaces which is updated on each method call and ask it for a correct version of the “size” method. Maintaining such stack is not that hard, but method call becomes more complicated and slow: late binding overhead sums up with the namespace selection. Finally we have two virtual tables: for the eigenclass and for the namespaced extensions to that class.
2. In a statically typed language we know the type of the object from the lexical context. Thus, it is extremely easy to bind the correct version of the method according to that type using pattern-matching mechanisms, for example (see Haskell).
3. In case of polymorphic types, we have to curry type information with the objects and determine methods based on the lexical scope. However, we may reduce overhead if we use polymorphic virtual machine: such machine which injects itself into a compiled piece of code with its namespace in mind. In such case, message send is executed differently depending on the lexical scope of the code, where the send is performed. This allows us to avoid virtual table scans. But we have to waste memory keeping namespace-specific pieces of executable code.
