Please join me at my new location bryankyle.com

Sunday, February 17, 2008

Curried Functions

So, currying, what's that all about?

Currying is a technique of transforming a function that takes multiple arguments into a function that takes one argument. In short, it's a way of defaulting parameters of a function call.

In a language like Java, you could accomplish the same thing by delegating method calls. For example:

int add(int a, int b) {
   return a + b;
}
int add_one(int b) { return add(1, b) }

However, since functions aren't first class citizens in Java you're limited in what you can do. In a functional language, the possibilities are a more open. You can make use of currying to reduce the size of your code base and reduce the amount of boilerplate code you'd otherwise have to write.

An example of this is a set of accessor methods where the code is boilerplate. Modern IDEs will generate these for you, but wouldn't it be nice if you didn't have to see the code for them all the time? What happens if some of your setters need to manipulate the value being set? I suppose you could find all of the setters and update them manually...or if you're working in a functional language, you could just leverage the features of the language to make your job easier.

Take a look at the following code:

function set(attribute_name, value) {
   this[attribute_name] = value;
}
function get(attribute_name) { return this[attribute_name]; }
function attr_reader(attribute_name) { return function() { return get.call(this, attribute_name); } }
function attr_writer(attribute_name) { return function(value) { set.call(this, attribute_name, value) }; }
function MyClass() {} MyClass.prototype.setName = attr_writer('name'); MyClass.prototype.getName = attr_reader('name');
var o = new MyClass() o.setName('Bryan'); o.getName(); // Bryan

In this example, we have two methods: set and get which are the most simplistic and generic setter and getter functions one could write. We've also added a currying function for each of them. We then call through the currying functions to create a curried call to getter and setters on the prototype of the constructor for MyClass.

While this example is not the best possible code for currying getters and setters I believe it illustrates the concept of currying.

If you can tell me why attr_reader and atter_writer return the functions curried using their call method you get bonus points. If you can't, I'll explain later.

Tuesday, February 12, 2008

Closures and Javascript

Ah Closures, one of the must misunderstood and accidentally used features of javascript. But why is this the case? Well, because it's so easy to accidentally use them few understand the mechanics behind them. In this post I hope I can clear up the confusion and explain how they work.

In computer science, a closure is a function that is evaluated in an environment containing one or more bound variables.

Or, in normal people terms, a closure is a function that can access variables from the same scope that it was declared in. You can think of it as a natural extension of the standard scoping rules where functions declared in the global scope can access global variables.

var my_global = "hello, world";

function printGlobal() {
   print(my_global);
}

In the above code the function printGlobal can access a global variable. As an extension of the same principle, in the following code the function printLocal can access a local variable in its declaring scope.

function main() {
   var my_local = "hello, world";

   function printLocal() {
      print(my_local); 
   }
}

So that's all well and good, but why on earth would you ever want to use it? All your life you've been told that global variables are evil (which they are), so surely closures must also be evil. Well, if used incorrectly of course they're evil, but with great power comes great responsibility.

Here's quick example of a function that returns a function to increment a value by another fixed value.

function incr(start, delta) {
   return function() {
      start = start + delta;
      return  start;
   }
}

var i = incr(10, 1);
i(); // 11
i(); // 12
i(); // 13

Pretty freakin' wild isn't it? But how does that work? When a call is made to the incr function start and delta are bound to its scope. The function it returns simply holds onto these variables. Since it has a reference to the variables (not just their values, but a place to store them) they can be freely modified.

The next question you might be asking is, "So that's all well and good, but what if I call incr twice and hold on to both of the returned functions? Won't the second call clobber the first?". The answer is: NO! Each call to the method creates a new local scope just for that invocation. Exactly the same as how two calls to the same function at the same time won't interfere with each other.

But by far, the most classic use of closures is to enable Currying, and I'm not talking about the delicious spice blend. No no, I'm talking about higher-order functions. Functions that work with functions. Functions that return functions that call other functions. Functions that I'll explain in another post.

Tuesday, November 13, 2007

The Next Javascript

Recently, I've been more interested in Javascript than I have been in a long time. However, after reading some of proposed features for Javascript 2, I feel like I'm watching a simple language with a few warts turn into a bloated C++.

From the proposal, I get the distinct impression that the committee designing Javascript 2 has some contempt for prototypical inheritance and dynamic typing. The proposal includes support for packages, classes, static typing etc. All things that appear to come straight from Java and other enterprise-y languages that I find are slow to develop in. Thankfully, it will be optionally typed, meaning you don't have to statically type your variables unless you want to. I haven't decided which side of the fence I fall on in terms of that debate yet, but I do feel like it statically typed languages can feel like a straight jacket from time to time.

All in all, the changes are way too much, way too quickly. For starters, all of the major browsers will need to support this new, hugely unproven language right out the gate. Undoubtedly there will be mistakes made in implementations, if they are even implemented at all. No one from the Web Development community will be able to use Javascript 2 at all being that it's so vastly different from Javascript 1.x and there is still a need to support older browsers for their applications.

You simply cannot force the sort of change this new language spec imposes in one go. It may as well be a new language for all the changes it includes. I believe, a more fruitful approach to moving Javascript 1.x to where this committee thinks it should go would be to incrementally add these changes to the existing language. I couldn't tell you where to start, as I'm fairly happy the current language, but I'm sure the community as a whole will be able to give feedback to the language designers in terms of what features are actually needed as opposed to what the designers think is needed.

In the end, if the committee goes forth with this specification for Javascript 2 it will be a long, hard, bumpy road to get stable, completely implementations in the browsers that are actually being used. Perhaps, more effort should be spent tackling the issues around the same-origin policy instead of giving new features that we can't possibly use for another 5 years.

Wednesday, November 7, 2007

Leopard

I upgraded to Leopard the weekend after it came out and so far, I've been pretty happy. There's only one thing I've noticed so far that's bothered me, Remote Desktop's VNC protocol is busted.

I did some research and it turns out I'm not the only person having this problem. Luckily, some of the others that have been having problems found out that they could connect using TightVNC. It's kind of a shame though, because RealVNC has been my Windows client of choice for the past few years.

So, while I wait for Apple to fix it, I suppose I'll have to settle with Vine Server which has worked flawlessly for me for years.

As a side note, I never knew that Apple had VNC support under Tiger until I started trying to find out why it's Apple would ship a broken new feature under Leopard. Shows how much I know.

Wednesday, October 17, 2007

Functions ARE Objects!

Javascript is a functional, object-oriented language - but what exactly does that mean to you a developer? It means that functions ARE objects. You can add members to functions just as you could any object. Take for example, the following function that keeps track of how many times it's been called:
function count_times() {
 count_times.call_count = (count_times.call_count || 0) + 1;
 print(count_times.call_count);
}
Trivial example I know, but let your imagination go wild.

Wednesday, October 10, 2007

arguments.callee

Javascript Tip: Ever wonder what arguments.callee is for? Well, it contains the function being evaluated, so you can write anonymous recursive functions like the following:
(function(n) {
  if (n > 1)
     return n * arguments.callee(n-1);
  else
     return 1;
})(5);
Which is the same as the following written in a more traditional way:
function fact(n) {
   if (n > 1)
      return n * fact(n-1);
   else
      return 1;
}

fact(5);

Saturday, September 8, 2007

Java 1, Bryan 0

Java is a really bad language for getting things done quickly. I don't mean in terms of processing speed, I mean in terms of the amount of time it takes to write something that works.

Friday I spent a bunch of time writing what I thought would be a trivial Java program with some pretty simple requirements. My program was to open a stream to a URL and pump a file at it. Additionally, I wanted my program to do this continuously with a bunch of threads.

After about an hour I had all but given up. In that hour I'd had problems with ports being left open, and data just not showing up on the other end of the connection. You might be tempted to say "oh the fool, he didn't close his streams", or "what an idiot, he never flushed the streams". You'd be wrong on both counts.

I probably missed something, but you know what? it doesn't matter. Java just isn't in the language to be using when you need to get things done quickly. Java is a systems language, not a get-things-done-quickly language. I really should have written this in something like Ruby or Python. The only problem is that while I know the syntax of these languages, I'm not familiar with the libraries.

I'm willing to bet that I would have been able to get this simple program written in about an hour, even without knowing the libraries, and it would have worked, unlike my Java version.