In this chapter, we have seen that Perl offers namespace partitioning, limited access protection, reflection, run-time subroutine loading (autoloading), package initialization and destruction constructs, and exportation of names to different namespaces. Let's look at some other languages with these features in mind.
Tcl's "package" feature basically provides a way to annotate a set of code with a version number and for the user of that code to explicitly state the version it requires. Tcl flags an error if there's a mismatch. Perl supports version numbers also (more on this in the next chapter).
Packages don't act like global namespaces as they do in Perl. Instead, Tcl supports the concept of multiple interpreters coexisting in the same program to provide completely distinct namespaces. This facility is used to create SafeTcl , which offers secure and insecure compartments in which to evaluate code. Perl's Safe package uses a completely different mechanism internally (neither packages nor multiple interpreters), as we shall see in Chapter 20, Perl Internals .
For reflection, Tcl has an "info" command for finding out about global symbols. It has no inheritance feature, but several free extensions such as [ incr Tcl ] and stoop attempt to fill the gap by providing an object orientation layer over the basic language.
Python offers packaging facilities very similar to Perl's. Each Python module is a namespace (a dictionary or hash table keyed by name), and Python allows you to traverse and query this dictionary. Like Perl, it does not enforce privacy of namespaces and leaves it to the programmer's judgment to respect module boundaries. As a module's user, you can import specific symbols into your namespace. (There is no mechanism equivalent to @EXPORT , which I think is a good thing.) Python does not provide anything like Perl's file-scope lexicals, which means that, unlike Perl, Python cannot give you true privacy if you need it.
Virtual functions in C++ provide run-time binding of functions. While compile-time type checking ensures that this is a safe binding, it also tends to make the code verbose in comparison to more dynamic languages such as Objective C or even Java.
C++ supports RTTI (Run Time Type Identification), but this feature is limited to finding the actual type of a pointer and to dynamically cast it. (The run-time environment throws an exception if a pointer is wrongly cast.) The facility does not tell you what a variable is really pointing to.
Java offers two levels of modularity: packages and classes , where a package is a collection of classes. (We'll learn about the notion of classes in the next chapter.) Perl's package is equivalent to both. Java does not allow one package to mess around with another package's namespace (no export) but allows a package to selectively import the classes it requires. It focuses a considerable amount of attention on security, which hasn't really stopped determined crackers. The Perl world has third-party packages called Safe and Penguin (which depends on Safe) that attempt to provide similar isolation characteristics (and don't offer any security guarantees either).
Since the arrival of the Java Beans and the 1.1 version of the Java Development Kit (JDK), Java has gained significant reflection capabilities, though nowhere near the amount of publicly available information Perl gives you. There are reasonably good arguments to be made both for providing this information and for not providing it; everything comes down to different models of programming. Men were sent to the moon while FORTRAN and COBOL ruled the roost, which proves that you can get a whole lot done if you don't indulge in language wars.
Java allows you to dynamically "dispatch" a function call, by giving the function's name as a string, and to trap an exception if the function doesn't exist; this is like using Perl's symbolic references.