When "unsafety" is a Good Thing
Some months ago, I read an article by someone who teaches Perl to Java programmers. In it, the author wonders a bit about some of Perl’s features which seem counterintuitive to those coming from a Java background. As you might expect, one of those features is its typing. He says:
For example: stern, protective type safety is not only missing from Perl but actually not even considered particularly desirable. Perl is relaxed. The reaction from students is, naturally: “Isn’t this a huge obstacle to getting anything done?” Obviously the answer is “No”, but even after all the Perl I’ve written I sometimes wonder why not. Is it really just the fact that it takes less time to type method signatures and variable declarations?
At the time I read this, I thought to myself, “Hey, I know the answer to that!” But I just jotted it down as a potential blog topic and let it percolate for a bit. Many folks reading this will also know the answer, but it’s an interesting topic, and I’m sure someone will get something out of it.
So, the first stumbling block in any discussion on this topic is to quibble over what we mean by “strong typing” and “weak typing.” Java (like C++ and C) is considered “strongly typed.” This is because when you declare a variable, you say “this is an integer” (for instance) and then you can’t put anything into that variable that’s not an integer. The compiler won’t let you do this—it’s not a runtime check (such as Moose has), but rather enforced at the very top level. On the other hand, Perl is generally considered “weakly typed” because you don’t say whether a variable is an integer or not, and you can stick whatever you like into it—integer, string, floating-point number, boolean value, reference to another variable: whatever floats your boat.
But some people argue that this is too narrow a view on typing. After all, when you declare a variable in Perl (or even if you never declare it), you say “this is a scalar” or “this is an array” or “this is a hash.” And you can’t put an array into a scalar, or a hash into an array. Isn’t that strong typing ... just at a higher level? Obviously the Java/C++/C folks don’t think so, but then they have a bit of a cultural bias as to what constitutes a “type.”
But let’s ignore that debate for the moment. Whatever sort of typing Java and its ancestors have, let’s agree to call it “strong typing,” just to save confusion. And we’ll agree to call the sort of typing that Perl has “weak typing.” Of course, even those terms have issues. Anything that’s “strong” has to be better than something that’s “weak” ... right? So it’s sort of like we’re insulting Perl’s type system before we even look at what it actually means. But let’s avoid the semantic argument as well, if we can, and just agree not to consider “weak” as equivalent to “bad” in this case.
So, which one is better, “strong typing” or “weak typing”? The answer, of course, is neither (or both, depending on your point of view). Both have advantages and disadvantages. This is one of the reasons I think Perl 6 gets it right: its system could be considered to be “optional strong typing.” That is, if you want “strong” (Java/C++/C style) typing, you can have it. If you prefer “weak” (Perl 5 style) typing, you can have that too. I hope that’s one of those features that gets backported to Perl 5 someday. But, the point is, sometimes “strong” typing is useful, which is why Moose provides a type system—which, as I noted above, doesn’t work the same way as true typing, but it serves the same purpose ... which is to help programmers catch mistakes. When you’re expecting an integer, and someone hands you a string, you’d probably like to know about it at some point before you try to divide 365 by “bmoogle.”
So Java and its ilk have us covered on that count: such an error would be impossible in those languages. But when is Perl’s “weak” typing better? Well, anyone who’s ever spent any time writing C code can probably tell you how annoying it is to put in all those
atoi calls. And, sure,
printf is nice when you need it, but what if you had to use it every single time you wanted to print anything that wasn’t a string? Trust me, it gets old fast. C++ makes it better, with its
iostream system, but then Java goes backward again (although admittedly not all the way back to the horrors of C). But none of them are particularlly easy. And printing (be it to screen or file) is a pretty common thing to want to do with variables. Sometimes you even want to read them back in from files, and that’s even harder. It’s much easier in Perl, which doesn’t much care whether a variable is supposed to be a string or a number. The ability to transition back and forth without having to think about it is pretty damned convenient, although anyone raised in Perl probably doesn’t even realize it, never having had to deal with the frustrations of a “strongly typed” language.
But let’s move beyond the simple case of trying to mix strings and numbers in output. In my experience, where a “weakly typed” language really shines is in trying to interface with your database. Your typical RDBMS is pretty “strongly typed,” which can make dealing with values coming out of it fairly annoying in a “strongly typed” language. You wouldn’t think that would be the case. You’d think that a “strongly typed” language and a “strongly typed” data source would be a match made in heaven. But what it actually means is that now you have to coordinate those types exactly, or you’re going to have troubles. What if your database’s concept of an
int and your language’s concept of an
int aren’t the same? Perhaps one is using 32-bit integers and one 64-bit integers. More commonly, what if your software doesn’t have foreknowledge of the types of your data? This can happen with dynamic queries, or just from using RDBMS functions. Sure, you can query the database itself and get column types back, but that happens at run-time, and your types have to be all set at compile-time. Quite a dilemma.
Even worse if you’re trying to write a general-purpose solution such as a library. I tried that, once, in C++. I cooked up some abomination of a class built around a union. I suppose, in the end, it was pretty much how an
SV (that is, the internal C representation of a Perl scalar value) works. Only mine was untested and most likely full of holes that the authors of Perl had found and fixed years prior. When I tried a few years later, in Perl, it only took a few hours to get the basics down. Because every column in an RDBMS query is a scalar value, and that’s exactly what Perl wants in a variable.
So it’s easy to see several situations where “weak typing” is an advantage. When you want to print a variable to the console, you don’t care what type it is: you just want to see it on the screen. When you want to pull a value out of your query and slap it into an HTML report, you don’t care what type it is: you just want to see it in the browser. Yes, there are times when “strong typing” is going to save your ass by catching a bad paramater to a method call. But there are also plenty of times when all it’s going to do is be a pain in your ass. And not buy you anything. And that’s why “weak typing” is a good thing.
And thus it is that lack of “type safety” isn’t nearly as unsafe as it sounds. And the time it saves you typing variable declarations really doesn’t enter into it.