Aaron Sherman's Tcl vs Perl Comparison

This document compares TCL and perl as general purpose scripting languages. Please note that John Ousterhout has always thought of TCL as a scripting language designed to be used from and with C, and as such some of the comparisons herein become more favorable to TCL. However, this is not how TCL is used for the most part. Most people tend to use TCL as a stand-alone scripting language, and thus the comparisons here are aimed at such efforts.

ajs@ajs.com or ajs@openmarket.com
WWW: http://www.ajs.com/~ajs/

In TCL, strings are C strings, so getting the length or adding to the end requires a search through the entire string for a nul. Since lists are implemented as strings, this leads to some costly handling.

In perl, strings carry a length, so getting the length is trivial and adding to the end does not require reading the rest of the string.

TIMES (length operations on a string; only min time recorded):

    Language:       String len:     Iterations:     Min Time:

    TCL              64             100000          22.57sec
    TCL             128             100000          23.83sec
    TCL             256             100000          27.25sec
    Perl            all             100000           1.08sec

This delta was so huge, that I thought I should check to make sure that perl wasn't optimizing my work away. I timed the following perl script:

 perl -le '$x="sadjflasjdfljaslkjashdlkfjhlskdfhkjaslfksadhfkjlhaslkjdfhlkasdh";for($i=0;$i<100_000;$i++)
{$z+=length($x)}print $z'

And it printed "6300000" (note this is a 63 character string, not 64, as was tested above). It completed in 1.09sec, and yes my TCL was compiled with optimization.

Perl handles strings of binary data just like any other string. Since it does not use nul-termination to find the end of a string, there is no reason for binary data to be different from text.

TCL uses nul-termination for all strings. This eliminates any possible use of binary data.

TCL cannot pass arrays by value or by reference. They can only be passed by name.

Perl arrays can be passed by value OR by reference. And, if you really want, they can even be passed by name.

Perl's method of handling installation and addition of new packages is so much more robust and clean than TCL it just doesn't compare. For instance with perl, I can get a new module off the net, run perl on the Makefile.PL, make, make test, make install and I'm done. If perl is in a strange location, the module will install there. If perl was compiled with some special command-line options, this module will be too. Later updates of perl will not overwrite this, since it goes into the a special area for "third party" add-ons. Perl also keeps track of what packages have been installed, and this can be viewed with the command: "perldoc perllocal".

With TCL there just isn't any such mechanism. The GNU autoconf system is supposed to be used by add-ons, but that does not provide any sort of installation management, and cannot find TCL when it has been installed in an unusual location.

Perl stores numbers directly as numbers, so math is much faster.

TCL stores numbers as numbers only within an "expr" statement. The return value of the expr is a string, and the parameters to it are strings, so you have to be able to do all of your math within a single expr for it to be fast.

Perl parses the script first, turns it into a syntax tree and optimizes it. This allows some types of optimizations that just aren't available to a true interpreter, which TCL currently is.

Perl comes with a full debugger which is closely integrated with the language ("perl -d script" puts you into the debugger).

TCL does not, although I have heard that someone wrote a debugger for TCL.

Perl supports the concept of name-space packages which can export their symbols to other packages as needed.

TCL is planning a name-space add-on at some point (may even be in 7.5beta in some form).

Perl does dynamic loading of modules in a fashion that requires the programmer to know nothing about the implementation.

TCL is planning dynamic loading at some point. Perhaps in 7.5beta.

In perl, anonymous subroutines can be passed around as arguments and treated just like a reference to a regular subroutine. Such subroutines can be used as closures (ala lisp).

In TCL, function names can be passed around, or strings which are to be evaluated as code can be, but neither of these fully replaces the value of anonymous subroutines, and TCL doesn't provide closures.

Perl's list is a true numerically indexed list. It also has hashes (associative lists).

TCL has only arrays (implemented as hashes) and lists (implemented as strings... YES, the WHOLE LIST is ONE STRING).

Perl has a simple preprocessor that turns prototype-like definitions of a library API into interface glue to perl which handles the type conversion of simple types and allows new conversions to be defined. This can be used to create static or dynamic access to an external library (eg. you don't have to install a new perl binary to get access to a library like a database library or even Tk).

TCL has a fairly convenient mechanism for adding new commands, but it requires writing a C function for each and every library API call that you wish to bind into the language, and no type conversion facility is provided (of course, there can't be one for complex types, since TCL doesn't handle binary data).

Perl has references which allows arbitrarily complex data structures including structures that are self-referential.

TCL uses strings to simulate nested lists, which can be put inside of a hashed array.

Perl can analyze a script for syntactic errors without executing it.

TCL cannot, because it parses and executes one line at a time.

Perl has an object-programming model. From the man-page:

A package can function as a class. Dynamic multiple inheritance and virtual methods are supported in a straightforward manner and with very little new syntax. Filehandles may now be treated as objects.

Someone has written a TCL add-on (incr tcl or itcl) which provides an object model with which I am not familiar.

Perl provides an interface to all of the POSIX (.1) routines.

TCL provides access to some of these as part of the language. Some others have been made available by add-on packages.

One interesting point is that TCL's original purpose as a command-line library is well suited to being used from perl. Perl is sloppy at best as a configuration file parser (it just isn't designed that way), and benifits gleefully from using TCL for such things. There is a "Tcl" module for perl which links TCL into perl and allows perl functions to be called from TCL and visa versa. This is a huge win for those who can step back from the religious debate of whose language is better and use the right tool(s) for the job. In fact, using that module provides dynmaic linking for Tcl (via perl's mechanism) which is terribly useful.

Aaron Sherman	"BOUNDARY, n.  In political geography, an imaginary line
		between two nations, separating the imaginary rights
		of one from the imaginary rights of the other."
		-Ambrose Bierce, The Devil's Dictionary
I-Kinetics, Inc.                        Pager: (508)545-0584
1 NE Executive Park                     Fax:   (617)270-4979
Burlington, MA 01803-5005               Desk:  (617)252-3489
ajs@ajs.com or ajs@openmarket.com       WWW:   http://www.ajs.com/~ajs/