Saturday, April 6, 2013

Lazy like a hummingbird


In my travels through the world of high level languages, the main language that caught my attention was Common Lisp.  I was drawn to it because it was the most powerful language I had ever encountered.  With macros, the full language available at compile time, restartable exceptions, the most powerful object system in computer science, it was hard to imagine a more expressive language.

But then I started looking into Haskell.  I've come to the conclusion that it is on equal footing with my beloved Common Lisp, if not beyond.  And now I'm starting to do work in it.  I had avoided that for a long time because while I realised Haskell was powerful, I was afraid the type system (good though it is) would be constantly in my way, reducing the value of the overall power of the language to me [1].  After using it for a few days now, I find that is not the case at all.  In fact, after one gets past the initial frustration of code not immediately compiling the type system becomes quite liberating.

I'm coding in Eclipse with the Haskell extension so the IDE can compile the code as I'm writing it and I get near instant feedback on any type errors.  Eclipse is pretty shoddy and not nearly as powerful as the Visual Studio+Resharper combination I work with in my day job but it saves time and appears to be the best option currently.  With this setup I can just make what ever changes I want and wait for the IDE to tell me what all I have to update.

Type Analogous


After spending some time building in Haskell I've come to realise that the Type system is to programming as Object Orientation is to global variables.  That is, OO didn't remove global variables it simply demarcated them.  It's still possible that a variable ends up with an unexpected value caused by some member function with no quick way of determining how it happened [2], but we can isolate exactly which methods could be responsible because non-members can't access the member variables at all.

The type system is similar: you can still have what ever types you want.  If you want a variable that can be an int, a float, a string or a character and automatically convert between the two you can do that.  But what Haskell's type system does for you is demarcate where this can happen.  You can still end up with a character where you expected a float, but only in those places were you've chosen those kinds of types.  Just as OO limits your global variable surface area, Haskell limits your type based error surface area.


All dressed up...


So what am I going to do exactly.  I'm planning on making a content management system in Haskell. :) I know about the web systems out there but none of them work exactly as I want.  I don't like most CMS because they require so many different technologies (i.e. moving parts) to get into production.  They all have to be front ended by some web server, a caching server, etc., etc. if they hope to achieve any kind of scale at all.

Haskell, in contrast, has Warp.  A fast web serving base that can break the dreaded 10k/s barrier.  Hopefully I can successfully leverage it to create something nice and unique.  If it doesn't work out, I'm sure I'll learn a lot at least.

My next series of posts will be documenting building the system so I suppose they can function as a kind of practical newbie guide [3].  You can also follow my progress (or lack thereof) via my repository.

[1] This might seem like an odd sentiment given that my day job is C# coding, but the C# type system isn't as strict as Haskell's.

[2] Well, a watch statement is pretty quick.  But seeing the offender in the stack trace is even easier.

[3] or maybe anti-guide!  If you want to use haskell use a pro like "Learn you a haskell" or "Real world haskel")

Tuesday, March 12, 2013

Dynamic scope pattern

[Noticed this was unpublished so I'll just publish it now]

Recently I noticed some confusion about dynamic scoping on Reddit. Many of the comments were even bashing dynamic scoping as something one would never need. The fact of the matter is you probably use dynamic scoping already, you just do it by hand.

What are global variables?

To understand what dynamic scoping is and why you are using it now, we need to understand global variables. So what is a global variable? A global variable is an implicit parameter to one or more functions [1]. Rather then pass some variable to 20 different functions, most of which simply pass it on to the functions they call, you make a global variable.

From this definition we can see that OO programing also has "global" variables. They are just restricted to specific classes (class/static variables) or instances of a class (instance variables).

Global variables, while convenient, a double edged sword. The problem is that any of these functions could change the variable without leaving a trace. That is, given the following:

int important_variable = 100;
void main()
{
first();
second();
third();
}

If the code crashes somewhere in second() or third() due to important_variable being changed, it is difficult to tell what changed it. If some function called by first() changed the variable then by the time one of the later functions crashes, the offender wont be on the stack anymore.

Dynamic scoping - global variables done right
One thing that would help with the above problem is if we could say that important_variable has a fixed value and can only be rebound within a specific context. This way, if our code crashes because important_variable was changed we can look at the back trace. The offending function will have to be in it. In C++ we might do something like this:

template class DynamicSet {
Value* _var;
Value _oldVal;

DynamicSet(Value* var, Value newValue) : _var(var), _oldVal(*var) {
*_var = newValue;
}

~DynamicSet() { *_var = _oldVal; }
}

void first()
{
DynamicSet(&important_variable, 9);
do_something();
do_something_else();
// ...
}

Here we take advantage of C++'s destructors to make sure the variable is put back as it was no matter how the current stack frame is exited. This is how dynamic scoping works.

Relationship between exception handling and dynamic variables

The reddit thread also mentioned exception handling. The interesting thing here is that exception handling can be implemented in terms of dynamic scoped variables (some languages do exactly that) and dynamic variables can be implemented with exceptions if you have restartable exceptions (I've seen a dynamic variable implementation in Squeak that worked like this).

[1] Well, it could be zero, but that wouldn't make much sense. :)