Friday, March 23, 2007

Indians (not) at the world cup...

Just when we were thinking this Indian side has the best shot at the cup, they go out and prove a point or two -- other teams are just better than them.

Wednesday, March 21, 2007

Closures in Javascript

I've grown up on C, and then a bit more on C++. I used to write a lot of networking and systems code, and then application level code to build backend distributed systems for an online retailer. Having dabbled a little bit in Java, and even less in Lisp, I've adopted Ruby as the language I mostly code in these days. But all these languages were a charm to get used to and develop in when I compare them with Javascript.

Why? Several reasons, but primarily because so much of the Javascript is about the browser, and while how you do something depends entirely on which broiwser your code is going to run on, there is hardly any good development and testing environment. To top that, I've not had the pleasure of reading a really good reference-like book for Javascript. If you know one, do tell me about it.

With the lack of books, one tends to rely on Google search to throw up some useful results. But some things are what you have to go through to pick up anyway. That brings me to closures. Though people have written about closures, they tend to only cover one aspect of lexical binding, and I wanted to add to this pool of collective online intelligence.

Closures let you define functions on the fly that are bound to the local lexical scope. Using these closures you can execute code that will use and affect variable references as available in the lexical scope of where the function is defined. Here's an example:


function f1() {

var letter = "A";
return function() { alert(letter); }

}

function f2() {
var letter = "B";
var f = f1();
f();
}

f2();


Run it here
.

The function f1 above returns a closure. The function returned is bound to the lexical scope of function f1. Once f1 is done, one would think that the all local variables etc are removed, and calling the function that is returned back by f1 should really use "B" as the value of the letter. Or maybe you would expect it to raise an error, because the scope of function f2 doesn't exist anymore. But if you run it, you'll still find that the function f returned by f1() call alerts with "A."

Once you see this, it is somewhat obvious what is happening. Except one thing, and we'll come to that shortly. What seems to be happening is that when the function in f2 is created (or rather the closure), it keeps track of its lexical scope. So all the references available in its scope are available to it. The reference that is returned is a reference to a set of code and its scope as was available then. That scope is what is used to execute the code in the closure.

What seems to be slightly less obvious is that the closure captures the references and not the values of these references in its scope. I.e., the closure does not copy all the values of the variables in its scope and keep them around for later. It keeps track of the references in its scope. If their values change by the time the closure is called, then the result would be different. Here is an update to the above example.


var letter = "A";
function f1() {
return function(callfrom) { alert( callfrom + " " + letter); }
}

function f2() {
var letter = "B";
var f = f1( );
f("call from f2");
}

function f3() {
letter = "C";
var f = f1( );
f( "call from f3" );
}

f2();
f3();



If you run the code above (here), you'll find that the call from f2 uses the value "A" for letter and the call from f3 uses the value "C."

The reason is again obvious once you see it, but it is easy to trip over this when using closures bound to variables in a loop. In the code above, f2 creates a new variable letter in its scope. This variable is not available in the lexical scope of the closure returned by f1. f1 uses the earlier defined letter. However, f3 does not define a new variable -- it updates the variable in global scope, the same variable that is also used by f1. The call from f3 to the closure evaluates the variable (the reference) 'letter' and it evaluates to "C" and not "A."

An important ramification of this is that when you are creating closures as callbacks inside a loop, and binding them to the variables that change with every iteration of the loop, you have to be extra careful. Unless you want to use these variables' values as they exist after the loop is done (or whenever the callback is called -- which might make it unpredictable), you have to create unique lexical references for each of these variables. A simple way to do this is to write a method that returns back the actual closure bound to its local variables. Every time this function is called, it generates a new scope for the closure. An example:




function myFunctor( x) {
return function() { alert( x); }
}

function testGoodFunctor() {

var functors = new Array;
for( var i = 0; i < 3; ++i ) {
functors.push( myFunctor(i) );
}
for( var j = 0; j < functors.length; ++j ) {
functors[j]();
}
}

function testBadFunctor() {

var functors = new Array;
for( var i = 0; i > 3; ++i ) {
functors.push( function() { alert(i); } );
}
for( var j = 0; j < functors.length; ++j ) {
functors[j]();
}
}

testGoodFunctor();
testBadFunctor();


If you run the code above (here), you will see three alerts with values 0, 1 and 2, followed by three alerts with value 3.

The reason, as you would have gathered by now, is that in the testGoodFunctor, each closure gets a unique reference for the alert call. However, the testBadFunctor provides the same reference "i" to the closure. When the closure is actually called, the value of i is the value it is supposed to have at the end of the loop.

There now, that's closures for you. And yes, there is one more thing to remember. Be careful not to use "this" to point to the object inside the closure (unless you know exactly what you are doing). "this" is not a locally defined reference, and when you closure is invoked, "this" may point to something completely different. If you want to invoke your methods on a specific object, it is better to create methods that are bound to the specific object. For example, like this:



function getObjectBoundMethod( obj, f ) {
return function() { return f.apply(obj,arguments); };
}

function f() {
this.g = function(x) { alert( "x = " + x ); };
var closure = getObjectBoundMethod( this, this.g );
return closure;
}

var to_call = f();
to_call(5);



Here, run it.

Update: Fixed the links to the running javascript samples.

Thursday, March 15, 2007

WC07 - Best Indian World Cup side ever?

1983 world cup happened when I was still too young to build a lot of memories. But I recall the years immediately after that, and the build up to the 1987 world cup. We all expected an India-Pakistan final. It was a team that had notched up some away one-day series wins, and looked good in general.

From then to now, India's fortunes have been mixed. India's never lacked some great cricketers in its team, who have bolstered India's chances and kept interest alive. But as a team they tend to falter more than they succeed. When we win a tournament, it is always somewhat of a surprise -- pleasant one, though. Until the recent spate of 17 wins in a row, Indian batting always felt brittle -- it would collapse under the mildest of pressures. The 2003 World Cup final was the ultimate let down.

However, there are reasons to hope for more from the current Indian team. The biggest reason I see for this is that there are a few players who fought hard to come back into the team and the team largely is made up of people with solid recent form -- except Sehwag, who seems to be the captain's gamble. Zaheer Khan and Ganguly would know the value of form and performing -- both having spent time outside the team and worked it back in. Tendulkar and Dravid remain the pole around which the Indian tent is pitched. And then there are Dhoni and Yuvraj. Indians have a decent bowling line up -- and I hope Irfan Pathan fires up.

Looking at the lineup, this may be the best side India have sent to the world cup. That said, wouldn't you agree that India is probably also the likeliest of the big teams to be upset by one of the minnows?

Tuesday, March 13, 2007

Cricket World Cup

Cricket world cup used to be an all-encompassing month some years back. Even now, I am pretty excited about some high quality cricket -- though I'll have to rely on youtube and the likes to catch the highlights.

As many have said, this is probably one of the most open world cups. Several teams have been gearing up for the contest well -- building up form and momentum for the event. I expect Australia, South Africa, India, Sri Lanka in the semi finals -- though New Zealand, West Indies and Pakistan can easily replace any of them. England, despite their recent wins, seems to lack the ability to make it to the last four. But then, who knows.

This is probably the last world cup for many greats of the game -- Tendulkar, Lara, Dravid, Ganguly, Gilchrist, Ponting, McGrath, Jayasuria, Shaun Pollock. It's a joy to have most of them in good form all at the same time for the world cup.

Thursday, March 08, 2007

Afternoons in Napa

San Francisco is a by any standards probably one of the best places to live. The restaurant scene alone in the city can spoil you to the extent you won't want to live anywhere else. And then there's Napa.

We've been to Napa a few times recently, not entirely by plan. We tried a few wineries -- not all of them by plan. The one winery we did plan for worked out very well -- the Caymus vineyards. If you are ever in Napa, plan for a visit to their tastings -- it's by appointment only, and their Cabernets are wonderful.

The other winery I've come to like a lot is the St. Clement. It is perched up on a small hill south of Calistoga, and the experience of sampling their excellent Cabernets and cheeses in their small garden overlooking the valley rejuvenates you more than a week in a spa.

World's Fastest Indian

A couple of quotes kind of stood out from this Anthony Hopkins movie. Inspiring, motivational quotes, if someone cares for them.

If you don't follow your dreams, you might as well be a vegetable.

Another one, on the similar lines.

If you don't go when you want to go, when you go, you'll find you've gone.
Lastly, something from Theodore Roosevelt. I am copying the entire original quote:

"It is not the critic who counts: not the man who points out how the strong man stumbles or where the doer of deeds could have done better. The credit belongs to the man who is actually in the arena, whose face is marred by dust and sweat and blood, who strives valiantly, who errs and comes up short again and again, because there is no effort without error or shortcoming, but who knows the great enthusiasms, the great devotions, who spends himself for a worthy cause; who, at the best, knows, in the end, the triumph of high achievement, and who, at the worst, if he fails, at least he fails while daring greatly, so that his place shall never be with those cold and timid souls who knew neither victory nor defeat."

Needless to say, everyone needs a motivational speech every once in a while. Something to keep the energy level high when chips pile up on the other side of the table. That said, I have always been on the cynical side of these motivational words -- I used to flaunt a poster from Despair, Inc in my office for a while. Maybe there's a middle ground somewhere. :)

Tuesday, March 06, 2007

The Lives of Others

I happened to see this wonderful film a few days back. It is a gem of a movie, fully deserving of an Oscar ahead of Volver, Pan's Labyrinth and Water.

People make a loot of hoopla over Water in India, and I found the movie quite ordinary. Deepa Mehta deserves accolades for her courage and conviction, but I've never felt her movies are great cinema.

Back to the German movie I started about -- it's worth seeing for many reasons. There was one thought that struck me that I kept thinking about afterwards. While the movie was about the 1984-ish East Germany, in some ways it was about a simple scientific principle as well. In any experiment one cannot expect to be a spectator alone and not impact the actual experiment -- by observing we become a part of the experiment, and that changes the outcome.

I highly recommend the movie. On another, though somewhat similar, note, I finally managed to watch the Hindi adaptation of "12 angry men." The Hindi movie is called "Ek Ruka Hua Faisla" and it's now available in Indian movie stores here in the US. The movie attempts to make a point -- expressly menioned at one stage -- that as a jury we need to keep aside our emotions and prejudices and judge objectively. That, my friends, is hard.