Method Dispatch Syntax
or, on the equivalence of the dotted member/method notation and the functional dispatch form.
Methods and functions
method num1 num2 call this the functional dispatch form
is somewhat akin to
in C++/Java or Python-like languages. For example, strings have a method called ""join""
''.join(list) ---> join('', list)
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).
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
obj.field = scalar setting a value in a struct
which reminds us of
scalar = obj["key"] lookup in a dictionary
obj["key"] = scalar insert into a dictionary
which is very similar to
scalar = list sequence lookup (list, string)
list = scalar injection into a sequence (list, string)
The connection comes direct from a language called Lua, where
obj.field = scalar
scalar = obj.field
are both syntactic sugar for
obj["field"] = scalar
scalar = obj["field"]
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.
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?
obj.meth ===> obj["meth"]
obj.meth ===> meth obj
obj.meth(param) ===> obj["meth"](param)
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.
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'
" - " `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).
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....