On Monday afternoon my Grandfather in Norway died. It's obviously a sad time for our family and Tai and I will be flying out to Norway today in order to spend some time with the family and for the funeral early next week.
When I wrote Why misunderstanding object orientation sucks I had no idea who Joe Armstrong was, even though I had of course come across Erlang many times.
I've still not learned Erlang, but I have been looking at how it handles message passing trying to see if there is anything to learn that is applicable to Mahlee™. I've been quite lucky in that Daniel Lyons, who really knows his Erlang, wrote a follow up to my post called Why Misunderstanding Concurrency-Oriented Programming Sucks. We've since swapped a few emails and he's very kindly explained a bit more about how Erlang works which has been very informative.
I've also been taking a closer look at how Google's MapReduce works and trying to think how all of this relates to how Mahlee™ does message passing and whether Mahlee™ requires any other primitives. I'd been considering the addition of stateless worker pools based on map or fold (MapReduce uses both).
My current thinking is that Mahlee™ doesn't need this. Mahlee™ was originally conceived of as a teaching and experimentation language and given that Erlang already handles a functional style of message passing there seems no point in also implementing it all for Mahlee™.
There is one thing that Mahlee™ does still require though. At the moment it is possible to wait on a future from a given object, but it isn't yet possible to wait on the first available future from a collection of objects. With the addition of this facility it should make implementing something like MapReduce in Mahlee™ much easier.
When people talk about C++ as an object oriented language they're really missing a lot about it. One of the things I love about the language is that it allows you to program in whatever style is appropriate for the problem at hand.
All of the low level thread handling that FOST.3™ implements and is used by Mahlee™ uses functional idioms—parameters are bound to functions and these are then passed to a work thread for execution. The result is passed back through a future.
Just to show the sort of thing that can be done, here is some C++ that illustrates the difference between partial application and currying¹ [1Many people use the term currying when they really mean partial application, a mistake I've made many times.].
#include <boost/function.hpp> #include <boost/lambda/bind.hpp> #include <cmath> template< typename R, typename V1, typename V2 > boost::function< R ( V2 ) > papply( boost::function< R ( V1, V2 ) > f, V1 v ) { return boost::lambda::bind( f, v, boost::lambda::_1 ); } template< typename R, typename V1, typename V2 > boost::function< boost::function< R ( V1 ) > ( V2 ) > curry( boost::function< R ( V1, V2 ) > f ) { return boost::lambda::bind( papply< R, V1, V2 >, f, boost::lambda::_1 ); } int main() { std::cout << curry( boost::function< float ( float, float ) >( std::powf ) )( 10 )( 3 ) << std::endl; }
papply
binds the first argument of a binary function and returns a function that, when the second argument is supplied, returns the result of the binary function.curry
builds on this to perform the curry type transformation. That is it takes a binary function and returns a function that when given an argument returns a second function that can have the final argument supplied.main
uses this to curry the std::powf
function and then supply the arguments one after another. It prints 1000.If you've not used the more advanced Boost libraries you really need to check them out.
On a final note we've had to move the server to yet another temporary home. Only time will tell what the internet connection will be like. So far there have been a couple of inexplicable outages lasting several minutes at a time.