I know this isn’t really the place to post code, and I’m sorry. But this is why I don’t like loosely typed languages. I was caught by a Javascript nasty earlier this week (no I don’t code professionally, this was for fun) which boils down to the code below. What you think could happen here…?
var problem_found = null; var listener = function(event){ /* Do something with event */ }; try { document.firstChild.addEventListener("click", listener, false); } catch (ex) { alert("Problem: "+ex); problem_found = ex; } if (problem_found) { alert("There was a problem: " + problem_found); }
You might have thought that either everything passes within the try block smoothly, in which case no alerts appear, or that there’s an exception in the try block and you get two alerts — one from the catch block and one from the if block.
And you’d be wrong.
Javascript actually allows you to throw anything. You should really throw an Error. But you could throw a String, or even a null if you liked. And if your code could throw a null then testing for null does not tell you if you had a problem. In the above example you’d get only one alert, from the catch block. If your problem-resolution code is in the if block then you’ll miss it.
Advocates of loosely typed languages will say that type problems can be avoided if you write good unit tests. But the problem occurred for me because this kind of mistake was in the JsUnit test framework, and it incorrectly showed a test passing. It took me two days to find the source of the problem. It turns out that the addEventListener() method above in Firefox 1.5 does indeed manage to throw a null if the listener parameter is not a function. Try changing it to a string and you’ll see this. My mistake was to pass in a non-function. Firefox’s mistake was to throw a null. JsUnit’s mistake was to assume a null exception means no exception.
Strict typing helps avoid problems that come about because we’re human and make mistakes. A wise man in ancient China once said “the compiler is your friend”. Javascript doesn’t have a compiler, and I can do with all the friends I can get.
By the way, you may be interested to know what the statically-typed Java language does. It doesn’t allow you to throw any object, but it will allow you to throw null. And if you do that it automatically converts it to NullPointerException. An actual, proper, concrete object. I know who my friends are.
But you could compile statically typed language to javascript :)
visit http://jsc.sf.net
I know this is old, but I never really felt like using the object that is thrown is a good practice. Honestly, you know if the catch block executes that there was a problem, so why not just say,
problem_found = true;
One thing I have learned is to expect that ‘null’ may exist where I don’t expect, and if I don’t have control over the object, then I certainly don’t know what to expect out of it.
I prefer JavaScript over Java only to the fact that I have much more freedom of expression, and I am not having to keep strict types. Strict typing only offers compile time safety and error checking, runtime errors are much more dangerous anyways. I one respect, JavaScript lets you concentrate on removing the more important errors. This instance I blame the interpreter, not the language.
aarondr, you’re right that it’s not good practice to use the thrown object to identify the fact of the exception, but that’s much easier to say that after the event. The pain I experienced was due to someone else’s very poor code which threw null. But it was allowed to throw null due to Javascript’s typing being so loose its trousers are round its ankles.
Meanwhile, I’m not sure about that particular argument in favour of loose typing. I wouldn’t speak too ill of loose typing — it certainly has its place. But just because a language doesn’t trap compile-time errors it doesn’t follow that it therefore helps you trap runtime errors.
This particular case isn’t actually an example of static typing helping you.
Null is a perfectly valid value for something of type Exception or Throwable to have in java, so from a typing point of view there’s no reason that null exceptions couldn’t be thrown around. What stops this from happening in Java is simply the special case you linked to in the JLS (and the fact that underneath, it’s almost certainly doing something like expression.getClass().isAssignableFrom(Throwable.class) during the throw and expression.getClass() obviously throws a NullPointerException if expression is null).
It probably would make sense for Javascript to do something similar – throwing null is almost certainly a mistake, so when it happens automatically changing it to an Error(“null thrown”) might be better.