The main point of my reply was the reworking of the closure, and although I did intentionally skip those error checks, I was too lazy to explain why. However, since you've brought it up, let's take a closer look:
This first test determines if $toggle is really an integer. My opinion on this is that if you want typed parameters, then go ahead and use a strongly typed language, but don't sprinkle your Perl code with ersatz type checks that work in convoluted and inefficient ways. Regexes are great for validating user input, but they're not good for patching Perl's weak typing with ad-hoc runtime error checks. If you must, write it like this:my $error = ''; if ( $toggle !~ /^\d+$/ or $toggle == 0 ) { $error = "The first argument to &alternate must be a positive +integer: $toggle\n"; } if ( ! @$items ) { $error .= "The second argument to &alternate must be an array +reference."; } die $error if $error;
Then you'll get a nice argument isn't numeric warning from Perl if you accidentally passed a string, which should be sufficient.die "Toggle not greater than 0" unless $toggle > 0;
Now look closely at the second error check. See anything wrong? The error message doesn't even correspond with the test. The error check ensures that $items is a non-empty array reference. In fact, if it's not an array reference, you won't even get to your error message complaining of this fact, as Perl would first die with the error Can't use string ("...") as an ARRAY ref. Perl already does that error check for you. But a user of your code might pass an empty array reference, see the error message claiming that he hadn't passed an array reference at all, and sit in bewilderment until he actually looked at your code, and saw the discrepency between message and test.
Despite that, you probably shouldn't even bother checking if the array is empty. Sure, it's a degenerate case, but degenerate cases are good to support when you're designing abstractions. Consider also that an array of only one element is another degenerate case. Should that too emit an error?
In your code, you've gone so far as to create a synthetic text accumulator to store multiple error messages. You'll also notice that the subroutine you named inside your error messages is different from the subroutine given. Perhaps that last criticism was below the belt, but it only serves to underscore my point that error checks aren't intrinsic goods. Error checking for the purpose of error checking is not wise. Like any other code, error checks will need to be maintained, they create the potential for new bugs, and they can adversly impact performace if poorly implemented.
So, before I add yet another error check, I ask a few questions:
None of this is to say that there are occasions were it's ok to not check for errors on system calls, or other external I/O. Paranoia about your outside environment is fundamental to good programming. But paranoia about the correct use of your own code isn't, and I dare say, it's even somewhat un-Perlish.
If I wanted bondage and discipline, I'd program in Java or Eiffel. As it is, I trust myself and my fellow coders enough not to feed a string into a subroutine that expects a number. I trust that if I did, I would locate that bug in relatively short order. And I trust that whatever bugs I do spend time fixing will be much more subtle and complex than the bugs that B&D programming and obsessive-compulsive error checking are designed to uncover.
MeowChow s aamecha.s a..a\u$&owag.print
In reply to Re: (Ovid - Golf for golf's sake?) Re(2): Simple Rotation
by MeowChow
in thread Simple Rotation
by Ovid
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |