Archive for October, 2006
Tuesday, October 31st, 2006
Semantical errors are a way of saying that when all else succeeds, you can still be wrong. The program compiles; it runs without any kind of run-time exception; it just doesn’t do what you intended. This is why you need system testing (see Chapter 6). (If you’re relatively new to Perl, this chapter might raise the hairs on the back of your neck a little. Feel free to return to it after you’ve gotten more comfortable with the language.) Here’s a tour of some examples of this obnoxious species of bug. 10.1 A Bit Illogical Perl has several ways of saying and and or: Table 10-1. And, Or, and Xor Operators in Perl Operation AND OR XOR bitwise (non-short-circuiting) & | ^ logical (high precedence) && || logical (low precedence) and or xor (There is no high-precedence logical XOR operator.) The consequences of picking an operator from the wrong row are usually annoying mistakes like open (FH, $file) | die “Error opening $file: $!n”; which dies whether or not the open succeeds, because the | operator is strictly a bitwise arithmetic or string operator, which evaluates both of its operands so that it can return the result of ORing their bits together. In this case, you want ||, which is a logical operator that evaluates its left-hand side and returns it if true; otherwise it evaluates and returns its right- hand side.
Note: If you are looking for top 10 and very good webhost to host and run your jsp application check Actions jsp hosting services
Posted in perl | No Comments »
Tuesday, October 31st, 2006
# Code to acquire a database connection atexit(&cleanup); # More database code which might fail } This ensures that no matter how that code block is exited, the cleanupsubroutine to break the connection gracefully will be run. 9.5 Confession Is Good for the Soul Sometimes your program dies not in your code but in some module you call suicide by association if you will. A module that wants to die is supposed to call Carp::croakinstead, because croakreports the location of death as the place the module function was called, not the line of code in the module function containing the croakcall. Some modules don’t do this. Either they call die, or they call another module that croaks; either way, you’re left with an error message that doesn’t tell you which line of your program caused its untimely demise. If this happens, here’s a quick way to force it to ‘fess up. Near the beginning of your program, insert the following: use Carp qw(cluck verbose); $SIG{__DIE__} = sub { confess @_ }; $SIG{__WARN__} = sub { cluck @_ }; Now whenever your program calls die/croakor carp/warnit ends up calling confessor cluck[9] instead, which have exactly the same effect except they print a stack trace of how they were called that goes all the way back to your main program. [9] Perl is nothing if not whimsical. Presumably in this case it helps to dispel the air of morbidity surrounding the whole topic of program death. Chapter 10. Semantical Errors “Pay attention even to trifles.” A Book of Five Rings, by Miyamoto Musashi
Note: If you are looking for top 10 and very good webhost to host and run your jsp application check Actions jsp hosting services
Posted in perl | No Comments »
Tuesday, October 31st, 2006
Bullet-proof your program by trapping exceptions and handling them gracefully. Let’s stop beating around the bush. What we really want is the ability to type exceptions and preferably also to subclass them, then catch them according to class while passing along instance-specific data.[8] Just like in Java. While we’re at it, it should use the same try … throw … catch syntax. [8] Not everyone thinks this way, just to be fair. If you’d rather stick with die… eval, you’ll be in plenty of company. It seems that the Perl mascot could just as well be a chameleon as a camel, since it can take on so many colors. An implementation of the try … throw … catch capability is in the module Error.pm by Graham Barr, on CPAN (http://search.cpan.org/search?dist=Error). It allows you to write things like try { # Some relational database-munging code. Somewhere # inside this something might raise an exception with # a line like: throw Exception::SQL (-text => ‘Bad SELECT statement’); } catch Exception::SQL with { # Code to handle SQL exceptions } catch Exception::IO with { # Code to handle I/O exceptions } otherwise { # Code to handle other kinds of exceptions }; Exception::SQLand Exception::IO are classes of exception that we created earlier by the simple expediency of inheriting from Error itself: @Exception::SQL::ISA = ‘Error’; @Exception::IO::ISA = ‘Error’; An alternative to Error.pm is Brad Appleton’s AtExit CPAN module (http://search.cpan.org/search?dist=AtExit), which allows you to specify a handler routine to be executed whenever the current scope is left for any reason, similar to the C++ auto_ptr template class. For instance: use AtExit; … {
Note: If you are looking for top 10 and very good webhost to host and run your jsp application check Actions jsp hosting services
Posted in perl | No Comments »
Monday, October 30th, 2006
but this is rather ineffectual for several reasons. First, we don’t know why the program is dying (without parsing the argument, which is an arbitrary string). Second, we don’t know where the program is dying without parsing the line number out of the argument (but when you think about it, that information is absolutely useless inside your program). And third, the Faustian bargain that this handler has made lasts only as long as it does; as soon as the handler exits, your program dies anyway.[7] [7] Unlike real signal handlers, which return to whatever code was executing when the signal arrived. Fortunately, there is an approach that solves two of these problems at the same time, which is to use the block form of the eval operator. Put the code you want to check on in the block, and if anything inside it causes it to die, Perl will transfer control to the end of the block and put the message from die in the special variable $@. For example, my %dotfiles; while (my ($username, $home) = (getpwent)[0,7]) { eval { opendir HOME, $home or die “$home: $!”; foreach (grep -f && /^./, readdir HOME) { open DOT, “$home/$_” or die “$_: $!”; $dotfiles{$username}{$_} = () = ; close DOT; } closedir HOME; }; # Note the semicolon that is required here if ($@) { print “Problem with $username, reason: $@”; } } Because we get to choose how much or how little code goes inside the eval block, we can determine the granularity with which we trap exceptions. This code which is building a hash-of-hashes containing line counts of dot files in users’ home directories uses evalto catch two possible exceptions (the failure to open a directory or a file, respectively) and then keeps going. To bail out as soon as we hit any problem, we would wrap the eval around the whileloop. A program will not exit if it dies for some reason while under the care of an evalblock. However, we still have to parse $@ after the block to find out why an exception occurred, if there were multiple possible causes. What’s useful about this method of exception handling is that inside the eval block, we could be calling subroutines to any depth, be deep inside a horrible mixture of our code and someone else’s libraries, and have no idea what might be going on inside them; however, if any statement in them issues a die, it will get caught by that eval block.
Note: If you are looking for best quality webspace to host and run your tomcat application check Vision tomcat hosting services
Posted in perl | No Comments »
Monday, October 30th, 2006
Other operating systems may handle this case differently. Because Perl uses the underlying operating system, you must be familiar with the quirks and gotchas that apply there too. In case you think it unlikely you’d write a program that created files and then removed them in the same invocation, think about temporary storage or checkpoint/restart capability. 9.3 Taking Exception to Yourself Having discussed how we handle exceptions generated by Perl, it’s time to talk about how we make exceptions of our own. You’re already used to the most basic exception-generating method, which is to call die. The arguments are printed, and your program exits with a nonzero return code. (Just which nonzero return code is documented in gory detail under perldoc -f die.) You may see some additional text output by die, such as the line number of code it died on. If instead it says (eval 13), it’s telling you that it was executing the thirteenth call to eval and prints the line number relative to the evaled code, not the program containing the eval. If it says chunk 42, it means that you had the filehandle FOO open and had made 42 calls to the readlinefunction (or <>) on it. If you didn’t change the $/ variable so that readline read more than one line at a time, newer Perls will say line 42instead. Maybe you’re tired of tacking ‘ or die…’ onto every system call and just want it to happen automatically. Well, as of version 5.005_03, you can use Lionel Cons and Ilya Zakharevich’s Fatal.pm and just specify for which routines you want this magical behavior to occur. Just list them in the use statement: use Fatal qw(open mkdir chdir); The routines have to be overridable, which is not something easily determined by mortals (translation: you have to look at the source). Bottom line: to see if it works, try it out on any core function you want to use it on first. Note that while you can do this for any function (including your own), it’s not useful for the ones like chmod, which return the number of files modified (unless you’re only ever going to modify one file at a time). Although you can’t use it on the execor systemcalls (for esoteric reasons), if you could, it wouldn’t be any good on system because that call returns 0 in the event of success. 9.4 Playing Catch-Up Let’s say that you want to go in the other direction and instead of turning errors into exceptions, you want to know when your program is about to die. The brute-force approach is to define a pseudo signal handler for __DIE__: $SIG{__DIE__} = sub { print “Igor lives!n” };
Note: If you are looking for best quality webspace to host and run your tomcat application check Vision tomcat hosting services
Posted in perl | No Comments »
Monday, October 30th, 2006
You’re not required to stick to only one idiom, mind you. It’s common for people to choose different ones according to the way they think about the operation they’re expressing. You have to be fanatical about checking return codes if you want to write quality programs. For instance, in the first example in the preceding list, the copyfunction from File::Copyalso returns true or false and sets $! on failure. It would be a strange sort of program that wouldn’t have a reason to ensure that this had happened. Some functions return something besides true/false but still set $!, for example, chmod, chown, and unlinkeach take a list of files to operate upon, return the number of files actually modified, and if there were any errors, set $! to the last one. (Unfortunately it’s not possible to tell which file(s) had problems without checking manually afterwards.) Know your operating system. A student in one of my classes encountered the following. The assignment was to create a temporary directory and a bunch of files in it, perform some operations on them, and then to remove the files and the directory. Part of his code looked something like this: foreach my $file (@files) { open OUT,”>$file” or die “Can’t open $file: $!n”; # write something to the file } # Open the files in the directory and do something # with the contents die “Unlink didn’t get everything: $!n” unless unlink @files == @files; chdir ‘..’ or die “Couldn’t go up a level: $!n”; rmdir $tmpdir or die “Couldn’t rmdir $tmpdir: $!n”; Every return code dutifully checked, but the rmdir failed, and $! said, “Directory not empty.” Yet when he looked in the directory, there were no files there. What was going wrong? The problem was that he had omitted the close statement from the loop that created the files. Whenever Perl encounters an open statement using an existing filehandle, it closes that filehandle for you, so all but the last file had already been closed. On Unix, if any process has a file open, it is not removed by unlink until the file is closed, so the last file in @files had not been removed at the time the rmdir was executed. But then the program exited, which meant that all its open filehandles were closed; at that point the file was removed, destroying the evidence.
Hint: This post is supported by Gama hrvatski web hosting services
Posted in perl | No Comments »
Monday, October 30th, 2006
15 $cases_sold->{$type} += $sold; 16 } 17 else 18 { 19 warn “I don’t know the food type $foodn”; 20 } 21 } 23 foreach my $type (keys %$cases_bought) 24 { 25 print $cases_bought->{$type} - $cases_sold->{$type}, 26 ” cases of $type on handn”; 27 } We used a function new to Perl 5.6.0, fields::phash, which takes the sting out of creating pseudo-hashes, and at the same time avoids the repetition we had on the first two lines of our previous version. If pseudo-hashes are retained in later versions of Perl but their implementation alters, fields::phash will be changed to hide that implementation change from you. When we want to iterate over the different food types to print our report, we just use the keys of a pseudo-hash (which means we no longer get to pick the order, unless we sort the keys). 9.2 Check That Return Code! The Perl built-in functions that might fail return a special value to alert you that they have done so. Usually, this value is false. (Functions that call out to the operating system to do their work will put the type of error in the $!variable.) This allows a number of common colloquialisms for checking and handling it, the most famous of which is the open-or-dieidiom: open DICT, ‘/usr/dict/words’ or die “I’m at a loss for words: $!”; This being Perl, there are many other ways of expressing the same thing. Pick one that works for you: if (mkdir $tmpdir, 0755) { copy $dbfile, “$tmpdir/$dbfile.$$” } else { die “Couldn’t create $tmpdir because $!”; } die “Can’t chdir to $subdir: $!” unless chdir $subdir; print chmod (0644, @files) ? “Success!” : “Failure: $!”;
Hint: This post is supported by Gama hrvatski web hosting services
Posted in perl | No Comments »
Monday, October 30th, 2006
keys you wish to use to the indices of the values in the array. This is much easier to understand with an example: [6] As of perl version 5.005_03. It is not only new, it’s experimental, so check the documentation for any version of Perl later than 5.6.0 that you have to see if it’s still in there. It appears from the latest discussions that it is unlikely to survive to Perl 6; however, being able to create hashes whose keys are fixed is so useful that the capability to do this is likely to persist in some form. $sound = [ { dog => 1, cat => 2, bird => 3}, ‘bark’, ‘meow’, ‘tweet’ ]; You must ensure that the numbers that are the values in the anonymous hash correspond to the positions of the corresponding values, but now you can say $sound->{dog} to yield ‘bark’. You could also get at it with $sound->[1], but that’s missing the point of a pseudo-hash. What you can’t do is put a new key in the pseudo-hash in this fashion: $sound->{frog} = ‘ribbit’; because that will generate an error (putting a new key in the pseudo-hash is possible but harder than that). But if your application doesn’t require inserting new keys at run time, this feature of the pseudo-hash will ensure that you are instantly alerted if you mistype a key. Because pseudo-hashes have an uncertain future, we won’t make a Perl of Wisdom out of them just yet. Evaluate the benefits of using them on a case-by-case basis. We have been making a more general point here that is worth a Perl of Wisdom: Force as many errors as possible to occur at compile time rather than at run time. This little program can be bulletproofed even further. It still requires the repetition of the keys vegetables and fruit in the pseudo-hashes and input recognition loop. If we could bind them together somehow, we’d have less of a chance of coming up with a compile-time error. Enter our latest revision. Here we’ve done some more radical surgery. You’ll notice that we’ve removed the need to refer to the hash keys while going around the input loop by creating the single hash %food_type to map from an inventory item to a vegetable or fruit. 1 use fields; 2 $_ = fields::phash(vegetables => 0, fruit => 0) 3 for my ($cases_bought, my $cases_sold); 4 my %food_type = (map ({ ($_, ‘vegetables’) } 5 qw(carrots broccoli kale spinach leeks)), 6 map { ($_, ‘fruit’) } 7 qw(apples kumquats pears bananas kiwis) 8 ); 9 while (<>) 10 { 11 my ($food, $bought, $sold) = split; 12 if (my $type = $food_type{$food}) 13 { 14 $cases_bought->{$type} += $bought;
Note: If you are looking for inexpensive but high quality provider to host and run your jsp application check Astra jsp hosting services
Posted in perl | No Comments »
Monday, October 30th, 2006
instead of vegetables the program would still run, but it would not produce correct output.[5] [5] It would generate a warning, courtesy of -w, in line 26 when we went to print a nonexistent hash entry, unless we were lucky enough to have mistyped vegetable in both places. Don’t enter the same text in different places in a program and depend on having to keep them in sync. Or at the very least, we would like the code to refuse to run if we did make such a typo. Perl 5.005 provides a new datatype the pseudo-hash which we can use here to accomplish that. In the following listing, it appears that little has changed structurally. But if you commit the typos we just discussed, instead of running, Perl instead spits out the error: No such array field at greengrocer.pl line 16, <> chunk 1 even if we misspell vegetables in the same way on both line 11 and line 21. 1 my $cases_bought = [{vegetables => 1, fruit => 2}, 0, 0]; 2 my $cases_sold = [{vegetables => 1, fruit => 2}, 0, 0]; 3 my %vegetable = map { ($_, 1) } qw(carrots broccoli 4 kale spinach leeks); 5 my %fruit = map { ($_, 1) } qw(apples kumquats 6 pears bananas kiwis); 7 while (<>) 8 { 9 my ($food, $bought, $sold) = split; 10 my $type; 11 if (exists $vegetable{$food}) { $type = ‘vegetables’ } 12 elsif (exists $fruit{$food}) { $type = ‘fruit’ } 13 else { warn “I don’t know the food type $foodn” } 14 if (defined $type) 15 { 16 $cases_bought->{$type} += $bought; 17 $cases_sold->{$type} += $sold; 18 } 19 } 20 21 foreach my $type (qw(fruit vegetables)) 22 { 23 print $cases_bought->{$type} - $cases_sold->{$type}, 24 ” cases of $type on handn”; 25 } A pseudo-hash bears some explanation, since it’s so new.[6] If the first element of an array is a reference to a hash, the other elements of that array can be accessed not just by their indices, but by using a reference to the array as though it were a hash reference whose keys were taken from that first element. The hash referenced by the first element must map the
Note: If you are looking for inexpensive but high quality provider to host and run your jsp application check Astra jsp hosting services
Posted in perl | No Comments »
Monday, October 30th, 2006
This kind of code is very common from a programmer who is happy to have identified the identical nature of the different sets of fruitand vegetablevariables and abstracted their use to a degree that they can be summed with the same code. However, the symbolic references are not necessary: not only do they break use strict, but they do not work with lexical variables, which is why this program doesn’t have any mykeywords. Well, that doesn’t sit right with Perl of Wisdom #8, so we should look for a way to write this program without dynamic variables. We don’t have to look far. Whenever you are tempted to create parallel variable sets, use instead a hash whose keys are the portion of your variable names that changes. Here’s the new program: 1 my %cases_bought = (fruit => 0, vegetables => 0); 2 my %cases_sold = (fruit => 0, vegetables => 0); 3 my %vegetable = map { ($_, 1) } 4 qw(carrots broccoli kale spinach leeks); 5 my %fruit = map { ($_, 1) } 6 qw(apples kumquats pears bananas kiwis); 7 8 while (<>) 9 { 10 my ($food, $bought, $sold) = split; 11 my $type; 12 13 if (exists $vegetable{$food}) { $type = ‘vegetables’ } 14 elsif (exists $fruit{$food}) { $type = ‘fruit’ } 15 else { warn “I don’t know the food type $foodn” } 16 17 if (defined $type) 18 { 19 $cases_bought{$type} += $bought; 20 $cases_sold{$type} += $sold; 21 } 22 } 23 24 foreach my $type (qw(fruit vegetables)) 25 { 26 print $cases_bought{$type} - $cases_sold{$type}, 27 ” cases of $type on handn”; 28 } Now, if it looks obvious to you that this first example should be using a hash, be aware that it is easier to fall into this trap than you might think, especially when you have a large program with a bunch of hitherto disparate variables that you suddenly realize can be treated similarly. Is this the best way to code this program? Hardly. We are repeating keys explicitly in two places where a typo would cause a problem. If we mistyped the strings in the $typeassignment or the foreach and it would be a natural mistake to type vegetable
Note: If you are looking for top 10 and very good webhost to host and run your jsp application check Actions jsp hosting services
Posted in perl | No Comments »