10.2 Tied Variables
Every substantive program uses many variables. In Perl, variables are scalars, arrays or lists, hashes and references. We also frequently use filehandles. Usually a variable or a filehandle is assigned values during a program; the values may be updated from time to time; and finally it is quite likely that we stop using the variable or it goes out of scope, or the program ends. Thus, usually, a variable is implemented directly, in the program, in terms of assignment and other statements.
However, we can think of variables in a more complex way. We can implement variables in terms of external modules or packages. The implementation can be as simple or as complex as the programmer wants. The package can implement anything it wants. In particular, the package can mimic the implementation of dbmopen and dbmclose, and perform more complex computation as well. Thus, in Perl, we can write a program that ties or links a variable name to a package that provides its implementation. A variable, whether a scalar, an array or a hash, can be tied to a package. In this section, we get a feel for it by looking at how hashes are tied. We do not delve into the details of writing a package that implements a tie. We see how packages that implement the tie of a hash variable to a DBM file.
There are several types of DBM files such as the following.
• NDBM
• BSD DB
• GDBM
• SDBM
• ODBM
Each type of file can be tied. However, not every type of DBM file may be available on every machine. Even if a DBM file type is available, the corresponding Perl module that performs a tie may not be available on the system. If simply the module is not available, it may be downloadable from a site such as www.cpan.org, The Comprehensive Perl Archive Network.
The first program we see below links an NDBM file to a hash. In order to be able to do so, we need to use a package called NDBM_File.pm that provides the implementation of the associated hash variable. It is possible to link the hash with other kinds of DBM files as well, using the appropriate package and if the other kinds of DBM files are available in the system being used.
In the program, we also use another package called Fcntl.pm. This package is called the File Control package. Fcntl.pm imports a set of names to the user program’s namespace. Examples of imported names are O_APPEND, O_CREAT, and O_RDWR. These are constants that are usually defined in a so-called header file in the C language. The imported constants can be used inside our own program.
Program 10.2
#!/usr/bin/perl
#file dbm2.pl
#Stores keys and values for customers in a a so-called NDBM database
use NDBM_File; #Uses a package that lets us us create what
#are called NDBM database files.
use Fcntl;
tie %CUSTOMERS, "NDBM_File", "customers1", O_RDWR|O_CREAT, 0644;
print "Hash %CUSTOMERS linked to NDBM file customers1\n";
%CUSTOMERS = (
"719-262-3432-1" =>
"Larsen::719-262-3432::larsen\@brain.uccs.edu"
);
$CUSTOMERS {"719-574-3656-1"} =
"Kalita::719-574-3656::kalita\@pikespeak.uccs.edu";
while (($key, $value) = each %CUSTOMERS){
print "Customer ID = $key; Value = $value\n";
}
untie(%CUSTOMERS);
print "Hash %CUSTOMERS de-linked from NDBM file customers1\n";
#********************
print "Linking again to and Printing contents of NDBM file customers1\n";
tie %CUSTOMERS, "NDBM_File", "customers1", O_RDWR|O_CREAT, 0644;
while (($key, $value) = each %CUSTOMERS){
print "Customer ID = $key; Value = $value\n";
}
untie(%CUSTOMERS);
The program dbm2.pl is similar to the program dbm1.pl discussed in Section 10.1.1. Instead of dbmopen to link a hash to a file, it uses the tie command.
tie %CUSTOMERS, "NDBM_File", "customers1", O_RDWR|O_CREAT, 0644;
The hash variable %CUSTOMERS is being tied. The class that provides an implementation for it is
NDBM_File.pm. There are additional arguments provided to tie in the form of a list. Of course, in Perl, the elements of a list do not have to be enclosed within parentheses. The first element of the list of additional arguments is O_RDWR|O_CREAT. These two are constants the are defined within the Fcntl.pm module. In this specific case, they simply say that the NDBM file should be created if it does not exist. If it is created, it is should be readable and writeable. As usual 0644 gives the permission mode if a file is created. This permission mode is used with umask, as discussed in the Section 10.1.1.1, to obtain the actual permission for the NDBM file created.
The rest of the program is similar to dbm1.pl, discussed in Section 10.1.1. The hash %CUSTOMERS is initialized with one key-value pair. As soon as the hash is initialized, its contents are written out to the associated NDBM file. Next, another key-value pair is entered into the hash. Once again, this pair is also immediately written out to the file. In this illustration program, the tie between the hash variable %CUSTOMERS and the associated NDBM file are severed after this by using the untie command.
untie(%CUSTOMERS);
If the hash %CUSTOMERS is updated beyond this statement, it is not reflected in the NDBM file.
To test that the hash’s contents are written out to the file as intended, we tie a hash again to the same NDBM file. This new hash is also called %CUSTOMERS although it does not have to be. The file name, of course, is the file written out earlier, customers1. Once the hash and the file are tied, we print the contents of the hash. We see that the contents of the hash are exactly what were written out earlier. The output of the program is given below. Lines have been broken where necessary to fit the printed page.
Hash %CUSTOMERS linked to NDBM file customers1
Customer ID = 719-262-3432-1;
Value = Larsen::719-262-3432::larsen@brain.uccs.edu
Customer ID = 719-574-3656-1;
Value = Kalita::719-574-3656::kalita@pikespeak.uccs.edu
Hash %CUSTOMERS de-linked from NDBM file customers1
Linking again to and Printing contents of NDBM file customers1
Customer ID = 719-262-3432-1;
Value = Larsen::719-262-3432::larsen@brain.uccs.edu
Customer ID = 719-574-3656-1;
Value = Kalita::719-574-3656::kalita@pikespeak.uccs.edu
Thus, using tie is a more generalized approach to linking a variable to a file. With dbmopen and dbmclose, only a hash can be linked to a file. With tie, any type of variable can be linked to any external module. In particular, if the variable implements how the contents of a hash can be written to a specific kind of file, and how the file can be accessed and updated, we get a module that implements the functionality of dbmopen and dbmclose. Of course, using tie, we can attach any type of variable to any module that does anything
its implementor wants to do.