Programming

Method Dispatch Syntax

or, on the equivalence of the dotted member/method notation and the functional dispatch form.

Methods and functions

In Haskell

method num1 num2     call this the functional dispatch form

is somewhat akin to

num1.method(num2)

in C++/Java or Python-like languages. For example, strings have a method called ""join""

''.join(list) ---> join('', list)

In Python, len(list) reminds us of list.length() in JavaScript, but why are there two distinct (non-equivalent) ways of saying this? Why is list.len() not part of Python? Because len is a built in operator for sequence types (dict, tuple, list, string) or classes that fake it (with a method len().

This is an example of building things into the language that could very definitely be generalized or built out of simpler constructs (like the way Scheme or Haskell do things, always in a simpler, more general (less ad hoc) way).

Fields

A separate notion got put into the mix with C++/Java (and Python kept it) in the OOP world

scalar = obj.field     getting a value out of a struct

or

obj.field = scalar     setting a value in a struct

which reminds us of

scalar = obj["key"]     lookup in a dictionary

or

obj["key"] = scalar     insert into a dictionary

which is very similar to

scalar = list[4]     sequence lookup (list, string)

or

list[5] = scalar     injection into a sequence (list, string)

The connection comes direct from a language called Lua, where

obj.field = scalar

and

scalar = obj.field

are both syntactic sugar for

obj["field"] = scalar

and

scalar = obj["field"]

(JavaScript works similarly.)

This is nice because it feels uniform. In this case obj is a table (similar to a dictionary in Python), which can also have numerical indices for lookup.

Observation

There is a strange problem of ambiguity if you want be able to store a function in a record struct. For example, how do you look up and apply method meth from object obj?

By itself,

obj.meth   ===>   obj["meth"]

not

obj.meth   ===>   meth obj

But

obj.meth(param)   ===>   obj["meth"](param)

and

obj.meth(param)   ===>   meth(obj, param)

seem equally valid.

We have to allow records to contain (pointers to) functions or functions would not be totally first class.

The goal of allowing this weird notation of obj.meth is to imitate how useful (and understandable) Python string manipulation is, when read (and written!) from left to right. If you type method calls in the order that you do them, then in the Python way it goes from left to right; in Haskell you have to double back and write the method calls to from right to left, adding parentheses to both sides of the expression. Wait... what about the . (composition) operator? Or the $ function application operator that can be used to avoid having to type the right parentheses?

I guess you can just define an operator (like --*gt; or something) that works like $ in reverse.

Example:

obj-->meth(param)-->meth2(param2)    ==>   meth2 (meth obj param) param2

which is a lot easier to write (in that order), and, as before,

obj.meth(param)   ==>   obj["meth"] param

Note that ""obj["meth"] param"" the dictionary lookup is actually done at runtime.

Also, the ability to use a function as infix is really nice, e.g. in Python

' - '.join(['a', 'b', 'c'])   ==>   'a - b - c'

becomes

" - " `join` ["a", "b", "c"]   ==>   "a  - b - c"

in Haskell. Join doesn't have to be a builtin method for strings; instead it can be grafted on after the fact in Haskell (which it is).

Conclusion

Haskell rocks. Also, I should read and write about slots in Smalltalk and Self (or Slate) because these people thought about all of this. To be continued....

Archive