
A late-night rant about OOP and parametric dispatch - joeyespo
http://devblog.avdi.org/2016/03/31/a-late-night-rant-about-oop-and-parametric-dispatch/
======
faaef
I don't really see a pervasive point to this rant. It is true that OOP can be
reduced to message passing, and that there's a specific style of OOP a lot of
people see as "OOP", but that doesn't mean that this style is "just obfuscated
procedural code, or uglified functional code". That OOP can be implemented on
top of functional style code, or procedural style code says nothing about it
being "true OOP" or not. For example, the great Common Lisp Object System is
built with functional primitives. And that makes it more elegant, not less.
Building an object system on top of a functional/procedural language is
syntactic sugar, and there's nothing inherently bad about it. After all we
write code for people to read.

~~~
LoSboccacc
I'd like the code complete approach. A method has 4 channels: api, status,
input, output.

Reducing how many channels interact semplify code a lot. Oop went for input,
status and statu, output pairs. Functional uses input, output and api, output
pairs.

Good programmers understand that and apply the one which is proper to model
their problem, to reach performance/memory goals and most importantly to
reduce te cognitive load of large codebases.

------
mcphage
This seems weird to post here. It's clear he's working out some ideas, but
hasn't gotten them clear enough in his head to take out of context and discuss
in a place like HN.

~~~
dllthomas
It does not seem to have been posted by the author.

------
javajosh
Consider this tree:

    
    
        dog
          bark
            softly
            loudly
          run
            fast
            slow
        cat
          meow
          purr
          run
    

Let's call this the coordinate-system of your API (I've extended it a little
hopefully to make it clearer). It's a small coordinate-system because it
doesn't take any strings, but whatever. 'loudly' only makes sense in the
context of 'bark', and 'bark' only makes sense on the context of 'dog'. That
list of nodes is a coordinate that identifies a unique position in the API.
(Note that in this API, actually just "loudly" should be enough to call the
right code, but that won't be true in general.)

To be formal you can pick out the code by saying `(do dog bark loudly)`, where
`do` is a reduction that concatenates and executes the code at each node.
(With a little constraining you could say `(do-special loudly)`)

OOP just calls these API coordinates by special impressive-sounding names. The
top level "objects" and the second level "methods" and the third level "method
arguments", and imposes all kinds of finicky constraints (some of which are
even useful). Languages differ wildly with these constraints: Java doesn't let
you have a unique instance method (well, not without either reflection or
bytecode manipulation, anyway), but Ruby does (lovingly called "monkey-
patching"). And it's quite rigid in it's current form, with a fixed
noun/verb/adverb structure.

At the end of the day all that detail obscures the simple truth that your code
defines a coordinate system and an invocation is a single coordinate. There's
a lot more to be said about this, of course! But I hope it helps/inspires.

~~~
rdtsc
According to Alan Kay true OO is message based. First you'd identify what the
objects are -- it seems dog and cat. Then you have a choice. Can either send
them messages which look like {bark, softly}, {bark, loudly}, {run, fast},
{run, slow}. Similar for cat.

Or can think of dog having an internal state machine and can be in two states
-- barking or running. When it is barking he can get two messages {softly} or
{loudly}. If it is running, can get fast or slow messages. There is a way to
switch from one state to another say getting a {bark} or {run}. Other messages
might lead to an error/exception.

This way the first way of doing things is just sending a message which both
switches state and regulates intensity of activity.

Heck pretty much a similar example is presented in Learn You Some Erlang For
Great Good book in the "Rage Against the Finite State Machine":

[http://learnyousomeerlang.com/finite-state-
machines](http://learnyousomeerlang.com/finite-state-machines)

(My favorite state machine is a that of a cat though in that text)

~~~
javajosh
Yes indeed. But what I'm saying is that there is actually just one nameless
state machine whose coordinate system is organized as a tree who's leaves
represent the machine's degrees-of-freedom. It's kind of an odd thing: the
leaf both partitions state, and it also co-locates the DoF for changing the
state (or at least it's apparent state, if you're immutable).

Neat link, I'll have to check it out. I've not done erlang but I'm quite
intrigued by gen_server in particular.

Sorry for talking about coordinate-systems: I can't help it, I have a physics
degree.

------
catnaroek
The author has no idea what “parametric polymorphism” means. It's not
“dispatching on all the arguments to a function”.

------
acjohnson55
What was so urgent about getting out this half-baked thought out that the dude
couldn't have waited to write something coherent?

If all you're doing is calling methods on objects with no supertypes or
private members, then yeah, you could accomplish the same thing by convention.
But once you start layering on more functionality in your object system, the
number of way you code encode this functionality starts to explode. Everybody
ends up doing things their own way, and there's no consistency or
compatibility. Sound familiar? It should because it's C.

~~~
VeejayRampay
Sincere question for you: Why does it bother you so much that someone wrote
something about something on the web (as hinted by your opening sentence)? Why
should we care that the thought is half-baked? Does it rob you of precious
space on the internets?

Sometimes, we just want to use the medium to share thoughts with people,
there's no cause to be annoyed or even condescending like that, it makes for a
horrible atmosphere where no one will want to engage in public discourse.

~~~
acjohnson55
Fair point. Maybe I was too harsh. I do believe that people should be able to
work out their ideas publicly. And perhaps it's not the author's fault that it
ended up on HN.

But the again, if you visit the blog now, the piece reads:

> Update: this post was the product of an exhausted mind, and as such it
> misused terms, wasn’t well backed-up, and was generally incoherent. I’m
> withdrawing it until such time as I can articulate these ideas a little more
> competently.

I look forward to the outcome of this.

~~~
VeejayRampay
And I agree with that. Avdi can be a great layman-oriented writer, he has a
knack for vulgarizing the cryptic, that article was not an example of that. It
was rushed, obviously. My point was about something else though, which we seem
to agree on.

Thanks for your response.

------
rdtsc
From Alan Kay's quote:

\---

OOP to me means only messaging, local retention and protection and hiding of
state-process, and extreme late-binding of all things.

\---

What is really described here is a dynamicly typed, actor-based language. I
can see a bit of truth in Joe Armstrong's joke that Erlang is the original and
true OO language.

------
white-flame
In a purely linguistic sense, the phrase "Object Oriented" does have some
affinity to single dispatch, because the dispatch is oriented around a single
special Object.

"Message Oriented" flows well into multiple dispatch, as the entire message
can be taken into account for determining the final method combination.

This of course is related back to the notion of a language focusing on the
nouns (Objects), or verbs (Methods, Messages): [http://steve-
yegge.blogspot.com/2006/03/execution-in-kingdom...](http://steve-
yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html)

~~~
catnaroek
> "Message Oriented" flows well into multiple dispatch, as the entire message
> can be taken into account for determining the final method combination.

I'm not sure about this. The metaphor is that you send a message to a specific
recipient, and the recipient figures out, independently, how to behave in
response to that message. So it still seems like single dispatch to me.

~~~
white-flame
In Lisp/CLOS-style multiple dispatch, the method you call is not associated
with any particular object. It's simply a dispatcher, and the objects are the
parameters/message contents.

So you don't send a message to a recipient object, but dispatch it using a
toplevel method name. I know that's a deviation from Kay's descriptions, but
it meshes well with the examples of multiple dispatch that I've seen.

Conceptually, "dispatch" can be understood as finding the recipient, not an
after-receipt task.

~~~
catnaroek
Yes, I know how CLOS works. It's certainly a powerful approach, but it doesn't
strike me as terribly... umm... object-oriented.

(0) In CLOS, as you say, methods are requests to the global _environment_ to
find the right behavior to perform on a list of arguments. In an object-
oriented system, each object has its own behavior, and the rest of the program
(that is, the environment) has no business knowing how it internally works.

(1) In CLOS, anyone can tamper with any object's slots, and this isn't even
discouraged. In an object-oriented system, the internal representation of an
object can't be directly manipulated from the rest of the program. The
behavior of an object is defined entirely in terms of how it responds to
messages.

That being said, you _can_ do object-oriented programming with CLOS. It's just
not the only, or even the main style that it supports.

For more information, see: [http://wcook.blogspot.com/2012/07/proposal-for-
simplified-mo...](http://wcook.blogspot.com/2012/07/proposal-for-simplified-
modern.html)

~~~
white-flame
> In an object-oriented system, each object has its own behavior, and the rest
> of the program (that is, the environment) has no business knowing how it
> internally works.

I would say that describes Erlang-style message passing, or maybe JavaScript-
style prototype OO. But in most "common OO" languages, I would say it's more
correct that each _class_ has its own behavior, not object. Of course, the
hidden state of an object can parameterize the class's behavior.

But still, there are many behaviors which differ based on the type or identity
of their arguments, but aren't well suited to be encapsulated into said
objects as they're equal peer parameters to the message, hence CLOS etc.

------
dale-cooper
I find clojure's multimethods
([http://clojure.org/reference/multimethods](http://clojure.org/reference/multimethods))
really awesome in the context of dispatching.

------
foota
Maybe we need some sort of hn robots.txt file to stop things from getting
posted before someone's ready for them to be :)

~~~
spriggan3
Or an HTTP code. WIP : 218

~~~
mwpmaybe
X-Hacker-News-Please-Stop

------
3pt14159
The issue to me is one of name spacing. Where is the XML#to_s defined?
Certainly not in one very large to_s function that takes in large swaths of
various types. Of course it should be namespaced around XML, the only issue is
whether it's module based or object based.

I think object based is better. Why? Because I can take the object and
introspect the methods. Any number of functions can take in an XML object, but
there are very few methods that the XML object needs to have. In my repl if I
do:

    
    
        my_xml.methods - Object.new.methods
    

I get a list of what I'm expected to do with this object. If I do something
along the lines of:

    
    
        functions.collect { |f| f.first_argument_can_be? XML }
    

Then I'm pulling in not just the normal functions, but also anything that
consumes _any_ instance of the XML instance, including domain specific ones.

Now, you could argue that all method-like functions should be namespaced to
their own module, but now humans have to be trusted to not define these
functions outside of that module and they have to be trusted to not define
anything else in the module. For what purpose?

~~~
true_religion
Elixir is a functional language, and has the option of modules and protocols
so you can define XML#to_string in two ways.

Either as a protocol so you could do to_string(this_xml)

Or as a function within the module so you could do XML.to_string(this_xml)

If you use the module function defintion you can import it into your scope via
import XML

then you can write to_string(this_xml) as if it were a protocol.

