Tuesday, 28 February 2012

Creating a function with a true name defined at runtime

Okay, I'll admit it, this is an obscure one:

I came up with a use case where I wanted to create a function that had a real name (e.g., shows in debuggers and such) that was determined at runtime. And as far as I can tell, the only way to do that is to use eval.

"eval!??!?!" I hear you gasp.

Yes, eval. eval is evil when you can avoid it (which is almost always), but with strings you're in total control of, in a scope you control, with an understanding of the costs (you're firing up a JavaScript parser), to do something you cannot do otherwise (as in this case), it's fine provided you really need to do that thing.

So having dispensed with the eval is evil meme, here's how we do it:

var name = /* ...come up with the name... */;
var f = eval(
"(function() {\n" +
" function " + name + "() {\n" +
" console.log('Hi');\n" +
" }\n" +
" return " + name + ";\n" +
"})();"
);

Live example | Live source

Pretty straight-forward. That creates a function with the name we come up with at runtime without leaking the name into the containing scope (and without triggering IE's flawed handling of named function expressions), assigning the function's reference to f. (And it formats the code nicely so single-stepping through it in a debugger is easy.)

Happy coding!

Sunday, 26 February 2012

Google Code - Error retrieving directory contents

I dropped by one of my Google Code projects, a trivial little jQuery placeholder functionality shim called place5, and was quite surprised to see, on the Source tab, the message "Error retrieving directory contents". Now, I have backups (and you do too, of anything you host externally, right?), so I wasn't panicked or anything, but I was still...jarred.

Some searching around revealed that people get this when they've changed their source control system (e.g., from mercurial to git, or subversion to mercurial, etc.). I hadn't changed my source control system, but looking at the Source tab again I saw that it was showing an empty git tree (with the error), and I thought: "Was I using git for this?"

Answer: No, I wasn't. I'd been using subversion. So what the...? So off to Administer, and under Source | Repository Type it said "default" (which appears to [now] be git). Setting it back to subversion corrected the error and restored source browsing.

I mention this for two reasons: Firstly, I figure I won't be the only one, so I thought I'd write this down in case someone runs into the same problem and finds this post. But secondly, it highlights a general principle: It's very useful to have your settings system have the concept of a "default" choice, so if you update defaults, people start seeing the new thing. But when you update a default that's going to break things for people, it's pretty important to change the setting for anyone using "default" to the new, specific choice for the old default. Because breaking things unnecessarily is doubleplus ungood, ya know?

Tuesday, 14 February 2012

Getting rid of "What's Hot"

Google have finally made it possible to get the "What's Hot" rubbish out of your main Google+ stream. Here's how:

  1. Go to Google+.
  2. Click "What's Hot" on the left-hand side.
  3. At the top of the page, there's a subtle little slider (basically an O on a line). Move it all the way to the left.

(If you don't see a slider at the top of your What's Hot page, just wait a day or two for the rollout to come to a server near you.)

That's it, you're done. Yay!

Friday, 10 February 2012

`forEach` and runtime cost

Just a tiny one today, mostly to write this down somewhere:

As you all know, ECMAScript5 adds forEach to arrays, where you supply a function that gets called for each element in the array. There are lots of benefits to this, not least variable scoping on the index and value variables and a bit less typing, but don't all of those function calls add up to a significant runtime cost?

No, they don't.

I got curious about it (I have a tendency to micro-optimize, which I'm trying to break myself of), so I tested it on the slowest (desktop) browser currently in use: IE6. Specifically, IE6 running in an old Windows 2000 VM I have lying around. I tested the performance of looping through a 100-entry array both with and without calling a function. Without the function call, IE6 looped through the array ~4,500 times in a second (that's 450,000 loop iterations/second). With the function, it managed ~2,000 times a second (200,000 loop iterations/second). So while that's a big relative difference (56% slower!), in real terms it falls into fergedaboudit territory: 2.78 microseconds of overhead. You heard, me, microseconds. That's 0.00278 milliseconds.

Now, I'm not going to say there aren't places where it could matter. I am going to say that they're going to be extraordinarily rare, I'd wager I'll never run into a situation where it makes a difference and nor will you. Whatever else you're doing in the loop body is totally going to wash out the function calls. Really.

Happy coding!