next up previous contents
Next: Perl on the Web Up: A Few Perl Functions Previous: pack and unpack   Contents

eval

The eval function takes a character string, and evaluates it in the current perl environment, as if the character string were a line in the currently executing perl program. At first, it may not be clear why this is useful, so consider the following example.

Suppose we have a configuration file for a program which reads its information from lines in the form name=value, for example:

     username=fred
     directory=/home/fred
     browser=netscape
     editor=emacs
We wish to create a series of variables inside the program which have the same names (with a dollar sign prepended) as the variables in the configuration file. Of course, we could write a loop which looks for all the possible values, but this is time-consuming, and, if a new variable is added, we may forget to update the program to allow for it. It's easy to parse the file; we can simply use split on each line, providing us with a name/value pair:
     ($name,$value) = split("=");
After reading the first line of the configuration file shown above, the variable $name would be equal to ``username'' and the variable ``$value'' would be equal to ``fred''. What we want to do is to create a perl variable called $username with the value of ``fred''. The first step in using eval is to create a character string in perl representing the command we wish to execute. In this case the command would be
     $username = "fred";
When using eval in a setting like this, it's very important to make sure that the command eval evaluates is the one you want; thus it's very important to print the command first to insure it's done correctly. With the name/value pair described above, the correct command would be
     print qq{\$$name = "$value";};
The qq operator is very handy, since it eliminates the need to escape the double quotes. Note that the first (escaped) dollar sign will literally print as a dollar sign, and the variable $name will be interpolated in the usual way. After verifying that this produces the correct statement for evaluation, we can use a program like this one to read each line of the configuration file and create the necessary variables (assuming the filehandle {CONF} points to the file in question:
     while(<CONF>){
         chomp;
         ($name,$value) = split("=");
         eval(qq{\$$name = "$value";});
     }

eval works by creating a separate perl environment which shares the same namespace as the currently executing one. Thus, statements executed in eval's environment take effect in the current environment as soon as they are encountered by your program. The fact that eval produces a separate environment for execution of its statements is capitalized in a second, different use of eval, namely to allow exception handling or error trapping.

Error trapping is important because there are times when you may call a function which has its own error handling mechanism; in particular, some programs will cause your perl program to terminate if they are not successful. Although there is no formal mechanism for exception handling in perl, it is very common practice to use the eval function's separate environment to carry out tasks that could potentially cause your program to terminate. If a problem does arise, only the eval's environment will be destroyed; your original program continues to run. When used for this purpose, the perl code to be executed by eval is surrounded by curly braces, instead of using parentheses as would be done with an ordinary function call. There must be a semicolon after the final curly brace, however. Such a construction is known as an eval block.

To facilitate communication from the eval's environment to the original program's environment, perl provides the $@ variable, which is set to an error message from perl if perl encounters an error in the eval's environment. To detect other errors, the $! variable can be examined. If used in a numeric context, it returns the last error code reported by the operating system; in a string context it returns the corresponding error message. While not completely reliable, it's the only consistent method available to perl to report the nature of errors beyond it's control.

As a trivial example, consider the problem of division by zero. Suppose we run the following program:

     $a = 7;
     $b = 0;
     $c = $a / $b;
     print "That's done!\n";
If we were to run this program, the message would never be printed, because the division by zero would terminate the execution of the perl interpreter. Note that in this simple case, the obvious solution is to check to make sure that $b is never zero, but it will serve as an illustration of the general principle of what to do when your perl program terminates unexpectedly due to some condition it encounters. We can solve the problem by enclosing the division in an eval block, and checking the $@ variable to see if problems occurred:
     $a = 7;
     $b = 0;
     eval{$c = $a / $b;};
     if($@){
        print "Uh-oh! $@";
     }
     print "That's done!\n";
The program will now print the error message as well as the original message, because only eval's interpreter died when the division by zero took place.
next up previous contents
Next: Perl on the Web Up: A Few Perl Functions Previous: pack and unpack   Contents
Phil Spector 2002-10-18