Archive

Archive for November, 2009

IRB for Javascript

November 21, 2009 ziggurism Leave a comment

When doing some heavy exploration in Javascript, I was doing most of my trials in Firebug. This is tedious for because the cycle of making code changes in a text editor, then reloading Firefox, then finally stepping through to my new code is too long if you’re doing small changes repeatedly and rapidly.

Ruby comes with an interactive command line console that lets you play with code interactively without any of the overhead of writing code. There’s no text editor, no saving files, no loading programs. You can execute and inspect each line of code as soon as you can type it. It’s a wonderful way to explore.

Other prominent interpreted languages Python and PHP both also have interactive modes, so I checked to see if there is one for Javascript. And indeed there is! It turns out that you can just install Spidermonkey, which is the Javascript engine of the Mozilla project, ie Firefox. That’s pretty much the canonical version of Javascript, as far as I’m concerned. I mean, Netscape invented Javascript, and this code is presumably a descendant of Netscape’s. The Ubuntu repositories include the Spidermonkey engine as a standalone command line tool, without the web browser as a dependency. It’s exactly what I was looking for. Nice.

I wonder whether I can find a binary to install on my Mac too. Or whether webkit has something similar.

Exploring constructors in Javascript

November 20, 2009 ziggurism 1 comment

I came upon this Javascript tutorial by jQuery inventor John Resig (nod to John Gruber). It covered several advanced Javascript topics with the goal of explaining to the reader the meaning of a particularly esoteric bind method from prototype.js. It was fun, and I followed most of it pretty well, although I got a little lost by the end in the section about Enforcing Function Context.

The tutorial included a lesson on pages 3538 about Javascript constructors which interested me.

First a recap of basic Javascript OOP. In Javascript, objects are defined via functions. To construct an instance of this function, you use the new operator, like so:
function foo(x,y) {this.x = x; this.y = y; }
var instanceOfFoo = new foo(1,2);

Whereas if you want to use a function as a function, you simply call it, like so:

function bar(x,y) {return x + y; }
var valueOfBar = bar(1,2); //this is the standard function call
valueOfBar = bar.call(this,1,2); //this is a more reflective call
valueOfBar = bar.apply(this,[1,2]); //this is even more reflective

So new functionName() to construct an instance of functionName, the OOP object constructor usage of a Javascript function. And just functionName() to to call the function and gets its return value, the functional usage of a Javascript function. Note that if a function is to be used in the functional manner, it must include a return statement; otherwise the value of the function all will be undefined.

The two uses of a Javascript function have different syntax and different semantics. And if you use one where you’re supposed to use the other, your code can fail in unexpected ways. In particular, if you accidentally leave of the keyword new, you won’t get an object, instead you’ll get the return value of the function, or else undefined if there is no return statement.

In addition to the standard Javascript function call, I listed two additional ways to execute a function call which could be said to be more reflective, ie instead of requiring you to write the identifier for the function statically in the source code, it may be determined dynamically at runtime. The first of the two reflective function calls is the Function.call method, which requires you to list the parameters explicitly. The second is the Function.apply method. The second is the more reflective of the two, because it takes an array containing all the arguments, which can be constructed at runtime, rather than requiring they be listed explicitly in the time.

Of note for this blog post is that there isn’t a builtin method like Function.apply which works when using the function as an object constructor. There’s some syntactical incompatibility between the function call and the object constructor which precludes from saying something like new foo.apply(array).

End elementary Javascript recap.

So in the Javascript tutorial, Resig demonstrates some code which ensures that even if you accidentally leave off the new keyword when constructing an object:

function User(first, last){

if ( !(this instanceof User) )
return new User(first, last);

this.name = first + " " + last;
}

The addition of the two lines of code in red give us the functionality to preclude calling this function as a function instead of an object constructor. So if the context in the function is an instance of the calling function itself, then the function was called correctly as constructing an instance of the object. Otherwise, it re-calls the function correctly with the new keyword. Pretty straightforward.

But this code is too static. First we have to reference the particular function we’re in. Then we reference it again, as well as the argument list. If you wanted to rely on this functionality, you’d have to include these two lines in every object constructor in your code, and you’d have to modify the lines for the particular function name and argument list. A massive violation of the principle of DRY.

So then Resig changes the first of the two lines to remove the reference to the function:

if ( !(this instanceof arguments.callee) )
return new User(first, last);

arguments is an array-like object available within the scope of every function. (To make an honest array out of arguments, use Array.prototype.slice.call(arguments)). It contains a list of all the arguments passed to the function (arguments[i] is the ith argument passed to the function), as well as a reference to the function that was called (arguments.callee). We compare the function to the context of the function. The context is available in the function via the this object. If you call the function as an object constructor, then this stores the object instance being constructed, and that object is an instance of function which was called. This this instanceof arguments.callee is true. On the other hand, if you call the function as a standard function call, then this is the global context, usually the browser window where the code is executing, which is, needless to say, not an instance of the function called. So this instanceof arguments.callee is false.

So in the first of the two lines of code, we've successfully removed the reference to the particular function by replacing it with arguments.callee. But it's still present in the second line. We haven't really solved the problem at all. This is where Resig leaves the issue, but I wondered if we could do better. It turns out that we can also replace the reference to the function in the second line:

if ( !(this instanceof arguments.callee) )
return new arguments.callee(first, last);

This is a little better, we've removed all explicit references to the function. However, we still don't have complete generality, because in line two, we still have to list explicitly the arguments to the function, so the code can't be reused without modification. But since we have at our disposal an array containing all the arguments, I thought we should be able to accomplish it. Just like Function.apply allows you to make a function call with arguments taken from the contents of an array, we need something analogous for object instantiation. Something like new foo.apply(this,arguments).

Unfortunately, the obvious guess doesn't work, and after fucking around with different options for a while, I couldn't come up with anything that did. So I turned to The Google, which as always, had the answer. Someone poses the exact problem I'm investigating on stackoverflow, and Matthew Crumley posts a solution:

function construct(constructor, args) {
function F() {
return constructor.apply(this, args);
}
F.prototype = constructor.prototype;
return new F();
}

function User(first, last)
{
if ( !(this instanceof arguments.callee) )
return new construct(arguments.callee,Array.prototype.slice.call(arguments));
this.name = first + " " + last;
}

I've tested this out and it does the job. I imagine perhaps adding it to the Function prototype, so that every function can optionally call it to ensure that it's only used as an object constructor. I do have to say though, I haven't been able to completely understand how the construct function works. It seems to rely on knowing how Javascript internally turns a function into an object, or some other magic that is eluding me.

It's mostly a moot discussion for me. I don't think I would make use of this function. Although I feel like Javascript ought to have an apply method for constructors, or better yet the constructor syntax should be more natural, somehow so that the two uses of the Javascript function are not distinct. But whatever, this is the way Javascript works, and I feel like we should learn it, rather than forcing it to change, rather than correcting it. So I don't see using this method. But it is instructive as a purely academic exercise to learn how it works and think about how it can be extended.

Ubuntu 9.10 again

November 8, 2009 ziggurism 1 comment

I recently posted about a very bad experience testing out Ubuntu 9.10 Karmic Koala. What happened, as it turns out, is that I had installed Ubuntu 9.04 Jaunty Jackalope. I went to ubuntu.com on release day, and I saw 9.10 available for download, but I followed the link for the official torrent instead. I guess I didn’t notice that the link was still for the previous release. I guess they hadn’t uploaded the torrent file for the new release on release day.

So I downloaded the new version. Everything worked swimmingly. The weirdness in the installer was gone; it correctly showed my unallocated space next to my Windows partition and changed the color when I selected the option to install on free space side-by-side. It of course didn’t prompt me to upgrade the OS. Network services were discovered via bonjour and printing to my MacOSX shared printer worked out of the box. The WiFi indicator light doesn’t blink neurotically. And the complete meltdown problem wherein it randomly re-mounted my root partition readonly has not showed up. It’s been stable and all around a pleasure to use. The graphics effects are smooth. I’m very impressed.

Obviously the 6 month old Ubuntu 9.04 Jaunty Jackalope had some incompatibilities with the hardware in my 9 month old HP Elitebook 6930p. The newer kernel and other software included with the latest offering from Canonical seems to support my hardware completely. This is usual with Linux, that there is some lag between new hardware platforms and their support in Linux. So I apologize for maligning the usability of today’s desktop Linux distro. It’s top notch, and it was only due to my own errors that I thought otherwise.

Tethering hack on the iphone breaks Visual Voicemail

November 3, 2009 ziggurism Leave a comment

When I first enabled the tethering hack on my iPhone running 3.0 via BenM’s help page, Visual Voicemail stopped working. I did not notice this, partly because I don’t get many phonecalls, but mostly because I just wasn’t paying attention. After a while I started getting annoyed that people were calling me and not leaving messages.

During my update to iPhone OS 3.1, after I restored from a modified version of the fresh Apple IPSW image, my phone declared that I had some 20 voicemails or so. Turns out people actually had been leaving me messages, and I just hadn’t been seeing them, since my VVM wasn’t working. Apparently there’s something incompatible in BenM’s carrier settings profile that breaks VVM when tethering is on.

A few days ago, I updated to 3.1.2 and reenabled tethering via a new, more intrusive and in depth hack. Today it occurred to me to test the Visual Voicemail, see if it’s still broken with the new tethering hack on the 3.1.2 jailbreak. Of course it is.

A quick turn on the internet reveals this gem. The instructions on that page led me to check my profile in Settings -> General -> Profile, where I saw that my original BenM profile was still loaded. I loaded the new profile from that page, and all works. Tethering is there, and VVM is there. I’m very pleased. Much thanks to redmondpie and w1kedZ of PeacefulInsanity.com. I note that BenM’s help page does say he’s working on a hack for 3.1.2, but for now, I’m all set.