A Dev Story: Functors

Picking up where we left off, the next logical step in building a parser would be to somehow define the interactions between data types. Now because this is 2012 and the olden days where procedural programming was the de facto standard are way behind us, we’d like for this script parser to support these minimum requirements:

  • Operators for every possible combination of Invariants ( +, – etc)
  • Function scope
  • Objects
  • Duck Typing

And we want to be able to do this in a reasonable amount of time, so of course hardcoding behavior on a per Invariant basis being a massive overkill from this point of view falls from the start. What we actually need here is a way to generate an abstractization of this behavior on which we can build when time comes.

Luckily here’s where we can take a lesson from the C++ architecture. You see, in C++ object orientedness is somewhat of an illusion propagated by the compiler, every member function you declare in a class is ultimately transformed into a procedural style function to which compiler passes the this pointer, which is why you can abuse the compiler and do stuff like the following:

class Foo{

 int Bar();
int Foo::Bar(){
#include "Foo.h" #include<cstdio> 
int main()

without fear of a crash. Beyond the fact that this serves to prove that C++ can sometimes resemble the goatse of object oriented programming, we can take a mental note on implementing the architecture we want. So we need a way to store functions in a invariant object and pass the this pointer at runtime when we call a function that we previously added to an invariant.

The next thing C++ can teach is that we can think of operators as functions, which is indeed particularly interesting because having decided that we want objects, we can now store operators as one of the functions the object has and call it when  we encounter it in our parser. This also has the advantage that we can name it to match the operator it represents so that when the time comes to interpret the parse tree, when you encounter an operator node all you have to do is call the method that matches the operators’ string.

This is where Functors ( short for Function Objects ) come in. You know how we defined an interface for the Invariant, something that all invariants should have so that we could let them worry about managing the state of the underlying data so that we can use types interchangeably in our script. Well this is what we’re going to do with Functors:

class Functor{

 InvUnknown* (*Func)(InvUnknown* args);
 Functor(InvUnknown* (*function)(InvUnknown* args)){
 Func = function;
 virtual InvUnknown* apply(InvUnknown* args){return Func(args);}

So basically we took a function pointer and wrapped it in an object that has the apply method so that we can call this function at our convenience.

Now here is where it gets interesting because as you can see the Functor apply method takes a InvUnkown pointer as a argument and returns a InvUnknown pointer itself. Well because the Invariant was designed to abstract data and since we can pass any type of invariant to the function, this means that not only can we abuse the List invariant to pass as many arguments as we want to the function (not to mention return as many values as we want from the function), but this way we get the Duck Typing as well.

And last but not least the function scope can be implemented by adding a map to the Functor object so that we can store temporary objects.

Up until now all is good in theory, but a real world example wouldn’t hurt, so allow me to demonstrate this by implementing a push function for a list.

First of all we need to update the InvUnknown class to take advantage of these functors:

class InvUnknown{
virtual bool inline is(inttype){returninv_type==type;}
virtual const string toString() = 0;
virtual void nativeCall(InvUnknown*param) = 0;
virtual InvUnknown* call(string& name,InvUnknown* params)
 Functor* method=methods[name];
 if(!method)printf("No method with name %s found",name.c_str());
   assert(params->is(LIST) && "Function parameters must be passed as LIST invariants");
 return method->apply(params);
 InvUnknown(int type){inv_type=type;} 
 void inline addMethod(string&name,InvUnknown* (*function)(InvUnknown*)){
 Functor* method = new Functor(function); 
 int inv_type;

Now we have the means to store and access Functors from our Invariant. Notice the native call though. In my opinion this is a hack that is unfortunately needed because upcasting in a base class is a definite no go and because the push Functor needs to take a list of values as a parameter, so the list has to be full when we call push.

Of course another solution would be to overload the apply method to take a vector<InvUnknown*> instead and it would basically be the same thing seeing as our list is in fact a wrapper for a vector<InvUnknown*>, but that wouldn’t be fair because that way you create an opening for bad practices. If the API you have to use in your code is the same as the one you expose to the script, this ensures that you are actually using what you create and you eliminate furstrations as you use it. Having a separate API that gives you more flexibility and or power than whatever you expose to the script usually shows that something isn’t planned right.

Onto the list definition:

class List:public Invariant<vector<InvUnknown*>,LIST>
 virtual const string toString();
 void inline nativeCall(InvUnknown* elem){data.insert(data.begin(),elem);}
 static InvUnknown* push(InvUnknown* args); } 

And the implementation

const string List::toString()
 stringstream buffer;
 string retval;
 buffer << "[";
 vector<InvUnknown*>::iterator paramIt = data.begin();
 for(;paramIt != data.end();++paramIt)
 if((*paramIt) == this) buffer << "this";
 else buffer << (*paramIt)->toString();
 if(paramIt != data.end()-1) buffer << ",";
 buffer << "]";
 buffer >> retval;
 return retval;
assert(params->is(LIST) && " ALL function parameters need to be passed as LIST objects");
List* paramList = (List*)params;
vector<InvUnknown*>data = paramList->getData();
assert(data[0]->is(LIST) && "List function push called on non list");
for(unsigned int paramIt = 1;paramIt < data.size();++paramIt)
 return parent;  

And last but not least the actual usage of the push function:

InvUnknown* l1 = new List();

InvUnknown* l3 = new List();
InvUnknown* l2 = new Primitive();
InvUnknown* args = new List();
string push_name = "push";
delete l1;
delete l2;
delete args;

Which produces the following output:


Which means that I can add Primitives (Invariant) and Lists and I can just as easily add just about any other Invariant I fancy, success.
Next time we talk a bit about scope.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s