Flutterby™! : Why I hate Perl

Next unread comment / Catchup all unread comments User Account Info | Logout | XML/Pilot/etc versions | Long version (with comments) | Weblog archives | Site Map | | Browse Topics

Why I hate Perl

2014-02-08 18:23:00.731958+00 by Dan Lyke 3 comments

When I took my current job, I was really optimistic. I had enjoyed writing Perl for my various personal sites, I had done a bit of Perl professionally back in the .com boom, and I thought that this was a chance to explore a language that allowed tremendous productivity in a professional setting.

Now, about two years later, I want nothing to do with the language. I'm rewriting the system which generates the static HTML at Flutterby.net in C++ (and quite enjoying both the typed language and the performance gains), I'm pushing towards other back-end technologies, and I'm trying to get into the habit of using other languages for my little utility scripts, just so I don't keep falling down into the Perl well.

What can I point to as the source of this turn-around? This isn't by any means exhaustive, but, in no particular order...

Perl is notorious for "TIMTOWTDI", "there is more than one way to do it". This makes Perl a wonderfully expressive language, but it also means that there's tremendous cognitive load associated with different coding styles. Consider a multi-line string. I have seen:

$a = <<EOF;
This is a multi-line


= "This is a multi-line\nstring\n"


= "This is a multi-line\n"


join('', map { "\n" } (qq/This is a multi-line/, qq/string/));

Unfortunately, that last one shows up far more often than it should.

Perl has no type safety, and the type coercion rules must be approached carefully. We've all made the goof of accidentally confusing scalar and list context (Although not all of us have been interrogated by the police after making that mistake, Flutterby link here). Of course smart coders will explicitly cast scalar() around code that they mean to be scalar, just to make the point clear, until someone doesn't and everything goes to hell.

I mentioned earlier this week about where 0.00000000000000711 became 7.11E-15 became $7.11. I'm not sure what the actual chain that led to this process looked like, but I can imagine. And, of course, the fact that there isn't strict typing means that the general edict of "currency must be in pennies" goes quickly out the door as soon as you get some guy with a CS degree on your team who hasn't thought deeply about what a divide means and not explicitly casting back to an int, or saying "Let me just round to two digits with a /^(\d*\.\d\d)/".

The standard solution to this sort of typelessness is to throw Moose at it. This feels really good, at first, but then the side effects kick in, and you're looking at a stack dump and thinking "how the heck did we get there?" and then the performance penalties bite you, and then you're back to "no, really, let's just put it in a hash and be done with it."

And, of course, Perl's system for references for complex data structures is basically like C pointers. Which is awesome if you're a C coder (I am), but it's hard to explain this stuff to people who learned programming in college.

Perl has no good SOAP environment. There are basically 3 different SOAP environments on CPAN. All of them are buggy in their own unique ways. You will end up sniffing the wire or otherwise hacking deep in the bowels of them to end up debugging interop problems, usually with people on the other end who are completely clueless because they're using Java and SOAP just works.

Dist::Zilla. Yeah, it's awesome. Until you can't figure out how to tell it to not include that one dependency which you can't install on the ancient production machine and which is only used in tests.

Speaking of which, Ruby has gotten really good about versionitis and packaging specific versions of libraries for a deployment environment. C and C++ are pretty damned good about this, either with static linking or with careful thought. local::lib is not a solution nearly as often as you'd like, and having version dependent library trees scattered throughout your deployment environment plays hell on security upgrades.

SSL and the various Perl sockets environments. Hate. Hate. Hate.

Character encoding. 'nuff said. If you're gonna fuck it up that badly, gimme back my goddamned pointer to bytes in memory and let me figure it out.

Many of these issues are exacerbated by the particular environment I find myself in, but my impression is that the Perl 6 wankery is making its way more and more back into Perl 5, with more emphasis on hidden side effects and "elegant" code which would be awesome if it works, but makes it completely impossible to figure out what the code is doing by looking at it.

And then we're in debugging and we'd be better off back in gdb and C, because there's just less abstraction to muck with.

[ related topics: Theater & Plays Interactive Drama Currency Maps and Mapping Writing Television Archival Education Work, productivity and environment Perl Books Databases Language Law Enforcement Software Engineering Nature and environment Open Source Heinlein hubris ]

comments in ascending chronological order (reverse):

#Comment Re: made: 2014-02-08 19:37:03.544197+00 by: Jack William Bell [edit history]

Feeling vindicated right now. I'll admit it.

I've spent the last twenty years telling people they would be happier with the results, on nearly every dimension, if they wrote it in C instead. (The most likely dimension C can fail on is Time-To-Market, and that is dependent on the problem domain. For those cases I recommend creating a Python prototype and re-writing the logic parts in C later. Another C failure area is Android, where the best option is still Java.)

For half-again that twenty years I have been tasked instead with writing systems in COBOL, DBASE, Visual Basic, Java, C# etc. etc. The only times C was considered an option out of the gate by management/customers was embedded work and Linux daemons. Still, other than Javascript, most of my professional work, even the non-C work, has been in a strongly typed language. (Yes, even Visual Basic can be a 'typed language'.) And the results still tend to hide problems in weird places. Any code doing pointer operations, which you don't KNOW is doing pointer operations, is code waiting to bite you in the ass.

C eliminates this concern because you are INTENTIONALLY doing pointer ops. It also forces you to think carefully about your data structures and APIs because you aren't hiding the details unless you make an actual effort to do so. And, best of all, it is FAST. There is a reason every language designer compares their language to C and then crows about the one algorithm that runs a few percent faster their way. (Never mind the fact you can probably re-code the C algorithm for better performance.)

Even C++ has some of these problems. For one thing, C++ has it's own bits of TIMTOWTDI. It always seems to me that C++ has 15 ways of doing anything, but everyone only learns one of those ways. The issue comes from the fact no two coders on a programming team ever learns the SAME way. Result: maintenance issues and debugging pain.

C for raw speed and simple simplicity and the cleanest OOP possible; using opaque 'magic cookies' and functions that re-cast them properly. Python for fast coding. Everything else for listening to your management/customers complain about the cost when you have to do a complete re-write of an existing code base in order to fix a few problems. Where's your cost savings from the higher-level language now?

#Comment Re: made: 2014-02-08 21:59:44.61335+00 by: spc476

I wrote one Perl program, maybe ten years ago (or a bit more) and now, I can't understand how it works. I remember it being somewhat of a pain to write, because of how Perl references work (stupidly, in my opinion) and that's what's making it hard to understand now.

These days, I use a mixture of Lua and C. Lua was designed to embed into a larger C/C++ application to make it scriptable, and thus, it's very easy to interface to C, but this leads to one of it's potential downsides: no batteries. The stock library it comes with is what you get with the Standard C library and no more. That's nice if you are actually embedding Lua in an existing C program, but bad if you want to write a program exclusively in Lua.

But being easy to interface, there are plenty of batteries (erm ... modules) to use if you want to do such things as Posix, networking, graphics ... (not to mention LuaJIT, a near drop-in replacement for Lua that generates native code on the fly).

#Comment Re: made: 2014-02-11 16:35:29.927163+00 by: Dan Lyke

I'll have to look at Lua, I've been hearing good things. The last time I wanted an embedded scripting environment, what I really wanted was the entire environment; I had a filesystem but naught else on that device and I was this close to writing a BASIC environment, because with line numbers and gets() comes a built-in editor...