back

by Rochus·7mo ago·view on hn ↗
> Kay's comments have always struck me as in line with Brad Cox's views

It is unlikely that the two would have agreed on this. Kay's view is actually based on messages, as implemented in Erlang, for example, and to some extent in Smalltalk-72. Cox, on the other hand, has implemented the object and dispatch model of Smalltalk 80, that Ingalls invented and published in 1978, almost exactly, even with the same method lookup caching.

> Cox's book uses this example a lot as a poor/insufficient substitute for dynamic dispatch.

The Wirth and Smalltalk approach are both fundamentally "late-bound search" mechanisms, differing mainly in whether the search state is optimizable by a central engine (VM) or fixed in the user's explicit control flow (Handler). This is a classic example of dualism in computer science, specifically the Expression Problem (or the Data/Operation duality). You are simply traversing a 2D matrix of (Types × Operations), just choosing a different axis as primary. It's mathematically isomorphic, both are performing a directed graph traversal to find the code that matches (CurrentType, CurrentMessage). Only the ergonomics and possibility for caching differ. Smalltalk hides the dispatch loop in the VM, which can do caching and the dispatch effort goes from O(N) to O(1) in time. Wirth exposes the dispatch loop in the WITH statements with a dispatch effort continuously O(N).

1 comments
Perhaps I'm misreading a different (opposite/orthogonal) intent from what you meant when you wrote the quoted passage in your initial comment. Some form of dynamism is required, else it fails the "extreme late binding" criterion that Kay insists is fundamental to his view of OO.

I'm not familiar enough with Smalltalk-72 or what Ingalls did that makes it so different from the Smalltalk-80 that Cox read about in Byte.

> differing mainly in whether the search state is optimizable by a central engine (VM) or fixed in the user's explicit control flow (Handler). This is a classic example of dualism in computer science, specifically the Expression Problem (or the Data/Operation duality). You are simply traversing a 2D matrix of (Types × Operations), just choosing a different axis as primary.

If you are doing whole-system development and have control over the entire thing (a "closed world" system), then it is that simple. But whether it's an open world or a closed world changes things.

Cox is fond of a simple example that he repeats in his book (fairly early on—it's on something like page 9) to demonstrate that dynamic dispatch is fundamentally necessary because it means you don't have to have panoptic control/involvement over the objects in a system (with all types known at compile time). If you're programming every operation with switch statements that select code paths based on objects' type tags, not only do you have to go visit all N routines where each of those N operations are implemented to update them when introducing a single type, but it also requires a priori knowledge of all types to be baked into the system that you release at the time of release, whereas OO on a live system means that you can introduce new types even after the initial system has shipped to the user.

Sure. Late binding in Smalltalk-80 means that a bytecode method is selected via a hash table per class and the address of the internalized selector string (atom) as a key. In Oberon, procedures are natively compiled, but each module is dynamically loaded; a module can implement a handler for a message and be separately compiled and loaded by name, so again late binding.

If you're interested in the difference between Smalltalk versions, I recommend Ingall's most recent paper: https://dl.acm.org/doi/10.1145/3386335. In contrast to Smalltalk >= 76, ST-72 had no bytecode, but sent tokens (synchronously) to object instances for parsing (which was called "message passing" by its authors).

> If you are doing whole-system development and have control over the entire thing, then it is that simple

The dispatch mechanism and the described duality is the same, whether whole-system or not.

> Kay's view of OO is a matter of "open world" versus "closed world"

Smalltalk was always a "closed world" (you are always in the same image, but code can be compiled on the fly at runtime), and all calls were synchronous. Since the Oberon compiler and system treats each module as a dynamic loadable entity and supports loading by name, it actually supports the "open world" approach. Interestingly, Kay's view is likely best represented in Erlang, where there are true messages sent asynchronously.

> If you're programming every operation with switch statements that select code paths based on objects' type tags

As mentioned, Oberon traverses the "2D matrix" from the other side. Each module may or may not handle a message in a WITH (i.e. switch by type) statement, but modules per se ar dynamic. So the "a priori knowledge" only applies to the message type.