Re: PYTHON VS. PERL VS. TCL

Tom Christiansen (tchrist@mox.perl.com)
16 Apr 1995 14:52:30 GMT

In comp.lang.python, John Redford <jredford@lehman.com> responds to
Steven Miale <smiale@cs.indiana.edu>, who responds to Sat Nashikkar
<snash@bnr.ca>, all of whom have been CC'd via email. If you haven't
read John originial article in
<9504131455.AA10039@seelebrennt.lehman.com>
then I advise you do to do so.

I'm just going to answer a couple of points here, hopefully filling
in what John wasn't sure of. In general, I agree with everything he's
said and respect his experience in these matters.

:> >1. Learning curve

Agreed: If you start with a Unix background, Perl is trivial to learn.
If you don't start with a Unix background, Perl is not trivial to learn.

:> >2. Ease of use

:Ease of use depend on what you are doing.. If you want to write
:networking code, then Python is BY FAR the easiest to use. Perl makes
:this about as hard as C would. I havent tried it in Tcl, but I suspect
:it is simply impossible.

No, that's no true. We're rapidly converging on a network module that
makes it trivial to say (for example):

require TCP::Client;
TCP::Client::connect("cs.berkeley.edu", "smtp");

I could give you a simple one of those right now.

I believe it was a darn shame that such things weren't provided
many, many years ago when perl first did networking.

:On the other hand, if you want to write a piece of reliable code,
:Python is your worst enemy. Python's practice of throwing around
:namespaces in the interpreted langauge makes it _inheriently_
:untrustworthy. Tcl restricts this type of game to the extension API,
:and Perl dosent do it noticably at all.

No, perl never grafts anything into your name space unless you ask
it to. e.g.

require POSIX;
POSIX::setsid();

But if you really want to, you can say

use POSIX 'setsid';
setsid();

:> >3. Portablility
:> Don't really think this matters; all three languages have been ported to
:> a variety of systems. Perl is mainly a tool language, and so really doesn't
:> have much to do outside of UNIX machines. Python has been ported to all,
:> and also has OS-specific modules for each platform (UNIX, DOS, etc.)

:These single minded replies.... The issue of where the interpreters
:have been ported is a simple one. If it has been ported to your
:platform, you can consider it, if not, then not. Case closed.

:The far more interesting issue of the portability of the code written
:in the langauge. Here perl is clearly superior because of the number
:of operations gaurenteed to exist on multiple platforms. I dont see
:why you feel perl is a Unix-mainly thing, or why a 'tool langauge'
:would be.

Quite.

This statement of "Perl is mainly a tool language, and so really doesn't
have much to do outside of UNIX machines" is truly mystifying. What's
a tools language? What's a non-tools language? While it's true that
Perl's been ported to virtually every Unix system in existence, it's also
been ported to Amiga, Atari, LynxOS, Mac, MPE, MS-DOS, MVS, Netware, OS/2,
VMS, Windows-NT, and Xenix. The number of MS-DOS, OS/2, and NT questions
on comp.lang.perl is going up all the time. I don't understand why you
think it doesn't apply to non-Unix platforms.

:Python's "os-specific modules" are some of the worst things for
:portability. There is no gaurentee that any operations will exist on
:all platforms, or even that operations will exist on any platform. You
:just get lists of what IS available, which is an impractical subset.
:The Perl strategy of providing a POSIX interface, and trying to
:provide all of the POSIX calls is a much better plan.
:
:Tcl just dosent come close in any of this, Tcl code is as portable as
:the extentions you use with it. Raw Tcl is portable because its dull.

Lamentably.

:> >4. Execution speed
:>
:> Tcl is pretty slow. I don't know what the speed difference between Python
:> and Perl is, though.

:Well I'll let ya know. Tcl is durn slow. Python is reasonable fast,
:and Perl is very fast.
:
:The only one this is an issue for is Tcl, which is just too slow to do
:a lot of work in directly.

Right. Then again, I don't believe it was designed for that, although
it is used for it. I'll append an article I wrote about this this morning.

:> >5. Extensibility
:>
:> Python. Writing a C module is trivial; all the examples and helper functions
:> that you could ever want have been provided.
:
:Well, I've written non-trivial extensions in all three of these
:langauges, and Tcl is by far the easiest to extend. Thats its claim to
:fame after all. Python and Perl are roughly equal. Python is not
:trivial to extend, because the programmer has to manage a lot of GC
:and thread issues in really crude and ugly ways. Perl is just slightly
:cryptic, but it is not terribly complex.

If you've been working with the API and MakeMaker folk, they've
been trying hard to make the extension process clearer, both via
interface and documentation.

:> >6. Development tools such as debuggers, profilers, code browsers
:>
:> Python has a debugger (pdb) and a profiler (profile); I don't know if it
:> has a code browser yet, but that should be easy to implement. Dunno about
:> Perl or Tcl.

:Well Perl and Python might be tied for 'what they have', but the Perl
:debugger is more powerful than the Python one, for what that matters.

Really? And you haven't even seen the new (unreleased) stuff. Cool.

:Tcl has no tools that _I_ know of, which means little, but I have
:found it impossible to write anything that needs tools to understand
:in Tcl. I'd think trying to profile Tcl means you're using the wrong
:language; seek speed elsewhere.

Hee. :-)

:
:> >7. Scalability, i.e. scope of application.
:>
:> Very; having OO and modules is a big win. I forgot what the largest Python
:> program is, but I believe it's well over 10,000 lines of code.

Um, exCUSE me? OO is nothing vagule resembling a panacea guaranteeing
"scalable" code. That's just BS that managers believe. OO doesn't make
good programmers out of bad, and the bad programmers will still manage to
write poorly scalable code whatever paradigm they adopt. It sickens me to
see how many blindly jump on the OO bandwagon for no good reason, thinking
it guarantees scalability, portability, maintainabilty, or proper design.
It doesn't. It's still up to the programmer, and the number of bad
programmers in this world so far exceeds the number of good ones that
it's enough to make you want to run an antique book store.

:Tcl is quickly nonscalable for the reason of speed. Perl dosent scale
:too well to very large data sets (though that may not be true now with
:perl5). Python is as scalable as you can get, with real pointers for
:memory handling and with reasonable speed.

Perl5 has real pointers. And it's arrays and hash tables have always
scaled well.
:> >8. Maintainability
:>
:> Same as above. Python lends itself well to good software engineering IMHO.

Frankly, that's a crock as far as I can see. Vide supra regarding OO
programming.

:All of these langauges lend themselves to good software engineering,
:and they are all more or less equally maintainable. That is, they all
:kinda suck.

Good programmer program it in themselves, the rest don't. And good
programmers are far harder to come by than most folks realize.

Actually, some of the 5.x compiler pragmata, warning-to-fatal promotions,
and module design technology actually do encouraging proper software
engineering, but again, the OO statement I made above still holds.

:Popularity means a heck of a lot by the way. The popular langauges
:get extensions written for them. The popular langauges have a much
:larger base of "testing by doing" going on and more people to provide
:fixed code. Popular langauges are learned by people before you hire
:them.

Larry Wall has been known to say he has the biggest software testing
organization in the world, although perhaps Microsoft's is bigger. :-)

Here's the article I posted this morning in which someone asked for speed
comparisons between perl and tcl. I suspect they also largely hold for
speed comparisons between python and tcl. Perl and Python speed comparisons
are much less dramatic.

--tom

In comp.lang.perl, mcdonald@cs.sfu.ca (Ken Mcdonald) writes:
:Well, I know there's no hard and fast answer to this, but I was wondering
:if there are any reasonable estimates as to how much slower (execution time)
:a typical Perl program might be, as compared to a C program to do the same
:thing. (If you could, as a bonus, throw in a comparison to tcl, that'd
:be great too!)

Perl code varies in speed considerably. In my experience, C code will range
from a bit more than 2 to as much as around 50 times faster than perl code
(that's O(e**1) to O(e**4), usually in the 5-10x range on average. You'll
tend towards the low end of that range if you can spend most of your time
in the perl functions that have been compiled into C, like pattern
matching. On the other hand, you'll tend towards the high end of the
range if you're spending all your time doing bit or byte compares, or
doing highly recursive function calls like Fibonacci (the latter due to
perl's stack overhead in processing function parameters, something which
is not unfixable).

:P.S. Was tcl derived from Perl, or vice versa? I've been using Perl for
:quite some time, and only just started looking at tcl, and while there
:are obvious differences, there are some very obvious similarities. (Both
:are about 100 times better than shell programming, so who am I to complain
:about either? :-) )

No, perl and tcl are unrelated. However, some of the superficial
similarities between tcl and perl are that both support interpolation of
variables into doubly-quoted strings and that in the absence of a return
statement, their functions both return the result of the last thing
evaluated. While they both appear to be interpreted languages, perl
is actually less of an interpreter than tcl is (vide infra).

In my experience, perl code will on average be about O(10**1) (call that
10x for now) faster than tcl code. That's because tcl is a pure
interpreter, whereas perl is a demicompiler; that is, it turns its target
program into an intermediary form and than executes that using its
interpreter, the same strategy that UCSD Pascal took. This approach
allows not only for increased performance over a pure interpreter, it also
provides for static, compile-time analysis (via -w and use strict, amongst
others) as well as a compile-time optimization pass that tcl does not --
and quite probably cannot -- do.

Like most shells, tcl is strictly a string-substitution language, which
has a number of serious side effects. One immediately obvious
ramification is the performance I previously mentioned: tcl does not store
its data or code in internal form, which means it has to re-parse it again
and again and again. "You want the 347th element of a list? Well, hold
on for a while as a I search for 346 nulls in this string first. You want
your data to be binary? Sorry, can't do that." It also means that each
time you use an if(), or each iteration of a while(), you just call them
as functions and they have to eval their second argument (which is never
cached in compiled form) -- AT EACH ITERATION! This is not very fast.

Apart from performance, there are some design drawbacks inherent in a
string substitution approach. For example, you can't convince the thing
that $a["10"] and $a["0x0A"] are different things. Along those lines, tcl
will spend a tremendous amount of time in string/number conversions,
because it never manages to cache the numeric value. Another drawback
that's even more serious is that everything is pass by name rather than
pass by value or pass by reference. If you read any CS text on compilers,
you know the dangers associated with pass by name. Another drawback is
that there are no real pointers/references, and thus you can't do type
checking on them, nor may you build up complex datastructures without
incurring severe run-time penalties, nor may these datastructures ever
contain binary data.

In one benchmark of an NxN matrix multiply of integers, perl performed a
good bit more than O(10**1) faster than tcl: in fact, tcl's performance
degraded non-linearly with respect to the size of the data set until it
was lagging behind perl by a factor of O(10**5). I kid you not. While
this is perhaps a pessimal case, it nonetheless demonstrates where tcl's
performance weaknesses lie.

Tcl also suffers even more than perl does in not always being clear to the
casual reader when something is being evaluated. Moreover, you are forced
to employ delayed evaluation and embedded substitute-evaluate mechanisms
to get things done. While we can and sometimes do resort to such measures
in perl, the practice would appear more pervasive in tcl. The immediate
shortcoming of this style is that it makes it harder to debug and maintain
such code. A more serious and subtle problem is one with which Steve
Johnson is rather annoyed (and not wholly without just cause) these days:
the inability to detect serious program flaws until actual execution
time. That means your disk backup system, petroleum processing plant,
medical monotoring station, space shuttle, or financial transaction
manager could in the middle of its operation blow up due to some
programming error totally undetectable until that particular branch of
code was hit under the right conditions. This is a scary thought.

On the other hand, that's not to say tcl isn't useful. It is. It simply
doesn't address the same problem domain as perl does. Because it doesn't,
you're comparing apples and petunias, and while we can play that game (in
fact, we are :-), it's inherently prejudiced depending on what answer
you're looking for.

Tcl imposes less syntactic grammar on you than does perl. Because of
this, it's better at being a metalanguage than perl is. By metalanguage,
I mean one from which you can craft your own private little language. And
making little languages is both fun and worthwhile, because it allows you
to produce a focused solution that allows for a simpler end-user specification.

Two examples of this are expect and tk. Notice how easy it is to specify
what you want to happen using them. Now, one could argue that it just
takes the right libraries, and that wit them you can do this in any
language. But that's just glossing over how easy it is in tcl.

Before release 5 it was somewhat difficult to do this in perl. Now it's
much less so, although still moreso than in tcl. Larry wrote a nice reply
once to Peter da Silva in which he showed that it was quite easy to craft
a make-like program in perl without subjecting the end user to an undue
quantity of confusing punctuation.

In my estimation, tcl is good for two things: the creation of new
metalanguage package (like expect) and interfacing with these. It is not,
however, a general-purpose programming language, and people who try to use
it as such will be laboring under severe burdens that probably cannot ever
be fixed due to the languages design criteria. That is, its strengths in
one area (metalanguage design) guarantee its weaknesses in others
(performance, compile-time analysis, etc).

If you read the older writings of John Ousterhout on tcl and contrast with
the newer ones -- or just listen to some of his talks -- you'll see that
he's changed his tune a bit about what tcl's legitimate and reasonable
problem domain is. I believe in retrospect that it was the language's
devout followers who pushed John into this stand rather than him trying to
push them towards it. Caveat emptor: Tcl shares the shells' (especially
ksh's) seductive snare in that it seems ok for a while, but by the time
you realize you're in too deep for what the language can provide, you've
already wasted a lot of time and effort.

While it's probably going too far out on a limb to say that perl is
actually a "real" general purpose programming language, it certainly
provides more inherent support for creating more "serious" (large and
complex) programs than tcl does. Of course, C wasn't designed to be a
general-purpose programming language either: it was designed to be a
systems programming language, which isn't quite the same thing. Likewise,
C++ is not an object-oriented programming language, it's a systems
programming language that offers a few (highly obfuscated, lamentably
enough) object-oriented features.

I would say that perl is a language designed for high-level, portable,
systems programming on tasks of small to medium scope, but with support
for enough underlying general-purpose programming constructs to make it
suitable for many users who would not characterize themselves as systems
programmers. This includes not just systems administrators but also
people doing software installations, rapid prototyping, generic data
munging, simple client/server programming, customer support, and test
suite design and analysis. Another application area for which perl
provides an elegant and convenient solution is one which is growing so
fast that I suspect even its second-derivative is still positive: World
Wide Web script support (a.k.a. CGI programming). I suspect than in a
few years, perl may well be better known as a CGI language than it is as a
sysadmin language.

--tom

-- 
Tom Christiansen      Perl Consultant, Gamer, Hiker      tchrist@mox.perl.com

lint(1) is the compiler's only means of dampening the programmer's ego.