Language Confusion

| Comments (3) | Software
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.

3 Comments

FYI, your table has an invalid python syntax for the for loop (no parens).

That only strengthens your point, of course.

Instead of using count(), you can use find() and compare to end(). This has the advantage that if you want to use an element if it exists, then you can use x.find() which returns an iterator, compare it to x.end(), if they are not equal, then you can dereference the iterator to get the value. It saves an extra look up.

It would be interesting to add in C# and java for comparison.

What rather peeved me about the Javascript farce was the way that Netscape just renamed their stuff Javascript without making any effort to make it in the least bit like Java.

Leave a comment