Unary Message Passing Revisited
More progress and more interesting linguistic artifacts, I was busy last night. I finally finished implementing an idea I had a couple weeks ago, which was to turn _() into a wrapper function that produced function objects to represent built-ins like Number, String, and Array. What it now does is generate a function with an eval property that performs the internal dynamic dispatch. I also override its valueOf and toString methods to return the value of a static closure. This has the downside of producing 2 functions per string or number, but it makes it possible to write:
Such that this function call returns:
where x is bound to 2.
I also took = and made it an equality operator ( not identity === ) and turned assignment into a right associative operator with a compile time look ahead. The look ahead is operator specific and prevents the dereferencing by default logic:
1 + 2 -> foo
which basically in English does the following:
- create a closure function object with a valueOf 1
- evaluate its '+' method returning a function returning _(1 + y)
- pass 2 to the function which returns a closure function with valueOf 3
- evaluate that function's -> method returns a binding function
- the binding function binds window'foo' to _(3)
You can then evaluate foo and get 3. Granted this is a special valueOf 3 so it responds to all the core function methods as well. Since the valueOf 3 result is also extended with Number methods like the wrapper function, it too can respond to () style invocations.
This is also working with Arrays. I have added the forth fetch @ operator to fetch the nth index of the array so:
3,4,5 @ 2
This also works with strings such that:
'hello' @ 2
There is still work to be done on Object wrappers, writing a better parser, and a lot of edge cases to consider. But this is very close to providing an interesting opportunity to produce new message based flow control constructors. Take ';' which in the current incarnation
Ie it replaces the top of the stack with it's right hand argument, effectively producing a new statement within a chained function call. This is a vital operator for doing a basic context change.
Drops 1 and replaces it with 'foo' which is then the current context for this.
If you think about it, nearly all flow control can be modeled in this fashion, and since every partial application returns a function we could do things like:
0 - -> negate ; 1,2,3 map negate
1 / -> reciprocal ; 1,2,3 map reciprocal
Where in Array map generates a function that walks the elements of the array applying the argument function to it.