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....