Software: August 2011 Archives

 

August 28, 2011

The (arguably counterintuitive) syntax for interpolating templates into other templates using jqtpl and Express is:

  {{partial(<variables>) "<inner-template>" }}

Concretely, if we have template X and we want to interpolate template Y with variable foo = "bar", then template X contains

  {{partial({foo:"bar"}) "Y" }}

This is probably not of interest to you, unless you just spent 10 minutes trying to work this out from the sparse (and I think in this case wrong; bug reported) documentation.

 

August 21, 2011

I recently upgraded to Lion. Probably it would have been wiser to wait until 10.7.1 but I wanted the PDF "signing" feature so I went ahead anyway. Overall, things went really smoothly. Notes below.

  • As everyone now knows, by default Lion is an app store only purchase and doesn't come with any kind of media. Apple charges $50 extra for a USB stick, but as I imagine most everyone knows, if you dig around in the install package, there is a .dmg file and you can burn that to DVD. [*] This seems advisable but takes some time.
  • The actual install was pretty fast, say about 30 minutes or so on my Macbook Air.
  • However, Lion comes with a new version of Filevault which encrypts the whole drive. Turning this on took a while to encrypt the disk but that can happen in the background, so it's not too bad as long as you're happy to have the machine on for a while as it happens, or you're willing to have it happen over a few days. Apple offers to let you store the recovery key with them. I declined this offer.
  • New Filevault works just fine with old Filevault, so if you've been using old Filevault you can transition easily. Every so often you get asked if you'd like to unencrypt your old partition, but Lion doesn't make you.
  • However, if you want Time Machine to work well rather than badly—which is how it has historically worked with Filevault—you need to move to new Filevault, which means encrypted backups. There is a setting in Time Machine to encrypt your backup disk. This takes a very very long time if you have an existing non-encrypted backup disk.
  • Installing Lion blows away your existing—or at least, my existing—copy of Xcode 3. Xcode 4 is now free, but this means that you will be without debugger, compiler, etc. until you download another 3GB worth of Xcode, so something to keep in mind. There's probably some way to patch in the old Xcode but this seemed inadvisable.
  • I'm mixed on the new gesture support. Obviously, I want the old scrolling behavior, not the "natural" scrolling behavior (where the scrolling goes in the direction of your finger like with the iPhone), but that's easily turned off. Mission control seems like it should be really cool, but other than periodically swiping to see it happen, I haven't figured out what it's for. (Incidentally, just this gesture stopped working on my magic trackpad, but not my built-in trackpad, necessitating a call to Apple support. Strangely, changing it from three fingers to two and back again solved the problem.)
  • The UI changes are all pretty subtle. I can take or leave the auto-scrollbars and the rounded dialogs, buttons, etc. seem fine. Probably the most noticeable change is the way that apps keep their state. I'm used to using Command-Q to quit the app, but now this means that if I quit Preview, and then restart it I end up with all the same documents I had before, so I'm not sure this is that great. I guess I just need to learn to use Option-Command-Q or reset the defaults using the command line.

Anyway, this was all pretty smooth for a major OS upgrade (I really appreciate not having to run mergemaster). And the feature where you can take a photo of your signature and embed it into documents really is pretty cool. I may never need to print-scan-sign-scan-email again.

 

August 3, 2011

Recently I had the dubious pleasure of working simultaneously in C++, Python and JavaScript. I'm not saying that there is anything wrong with any of these languages, but if you rapidly switch back and forth between them (as, for instance, when you're developing a JavaScript Web 2.0 application with the server in Django and the front end), things can get pretty confused. The P90x guys claim that muscle confusion leads to increased strength, but in my experience, programming language confusion mostly leads to problems.

The basic problem is that these languages have fairly similar syntaxes and so it's pretty easy to inadvertantly use the syntax of language A with language B. Here's a sampling of some common tasks in these languages:

TaskC++PythonJavaScript
Statement Separation; terminatednew line; semicolon separated (optional)
Length of an array v.size() (for STL vectors) len(v) v.length
Append to an array v.push_back(x) v.append(x) v.push(x)
Iterate through an array for(size_t i; i<v.size(); i++) for(x in v) for(var i=0; i<v.length; i++)
Is an element in an associative array? if (a.count(k)) if k in a if (a[k])
Creating a new object new ClassName() ClassName() new Constructor()

To make matters worse, sometimes what you would do in one language is syntactically valid, but undesirable, in another language and invalid in a third. For instance, in Python you don't use semicolons to terminate statements at all, but it doesn't choke if you use them. In JavaScript, you mostly need them and JS will "insert" them as needed [*]. In C++, semicolons are required and if you don't add them, the compiler will throw an error. So, if you switch back and forth, you're constantly adding spurious semicolons in Python code (which makes Python people sad) and omitting them in C++.

To take a more irritating example, consider asking if an element is an associative array. This is actually a lot more painful: if you do if (a[k]) on a C++ map, as is natural in JavaScript, C++ will automatically instantiate a new copy of whatever's in the array using the default constructor and place it at location k. This can have really undesirable consequences, since you've just modified the structure you mean to be examining. On the other hand, if you dereference a nonexistent location, it throws a KeyError, like so:

>>> a = {}
>>> a['b']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'b'
>>> 

Unfortunately, this is a runtime error, so it's easy not to notice this mistake until you get fairly far into the program, especially if you're just checking for existence as a corner case where the key is usually present.

Iterating through an array is another case where it's easy to mess up. In JavaScript, like C++, you iterate through an array by using an index from 0 to array length - 1. In Python, however, you can iterate through it more easily just by using for x in v where v is the array. Unfortunately, a similar construct is syntactically legal in JavaScript, but the result isn't what you want:

> a = ['a', 'b', 'c']
["a", "b", "c"]
> for (x in a) { console.log(x); }
0
1
2
undefined

Instead of iterating through the array, we're iterating through the array indices. Again, this is syntactically valid code, it just doesn't do what you want (though perhaps you might want to use this as an alternative to the familiar for (i=0; i<a.length; i++) idiom.) Unfortunately, if you don't test your code carefully, it might not be something you noticed. To make matters more confusing, the for (x in a) idiom works fine for another common data structure enumeration task: enumerating the keys in a map in both Python and JavaScript.

None of this is intended to be a criticism of the syntax of any language, the problem is the conflict between the syntax of each language. This is particularly troublesome for Web applications because the client side more or less must be written in JavaScript but the most popular Web frameworks are written in either Python (Django) or Ruby (RoR), so it's common to have to work in two languages at once. I don't even want to think about what happens if you have to work in a framework that uses Java, a language, which, despite it's name, is not really related to JavaScript, though they have confusingly similar syntax. This is one advantage of Node, a server for developing Web (or any other server) application in JavaScript. Since the client side being written in JavaScript is a fixed point, Node allows you to write your entire system in JavaScript. Of course, depending on your opinion of JavaScript, that may seem like a distinctly mixed blessing.