[comp.lang.perl] Some suggestions

nagler@olsen.UUCP (Rob Nagler) (02/09/91)

I second Mr. R. B. Jim's recent compliments about the "require"
operator.  It has saved me time and confusion.  I would like to see
this "assertion concept" extended.  Many of my perl programs are "silly
things".  I want these STs to work properly and don't care much about
speed.  It would be really great if there was a way to cause a
selected set of operations--don't ask, I haven't got that far--to
die() upon failure.  For example, a majority of my calls to open()
look like:
    open(FOO, "<foo") || die "foo: $!\n";

Yes, I could write a package called "assert.pl" and call &assert'open
instead of open.  Perhaps, I will do this.  There are other
operators for which this might be useful.  For example, close() doesn't
return an error code[*], but it can get write errors when flushing
buffers.  Another example, if a program reads past eof with <> which
only returns false once.  I guess it comes from my perspective that
certain programming errors are better stopped dead before they can
shoot something.

[*] Turns out that close does return an error code, but my manual
    (v3.27) doesn't say anything about it.  When in doubt, look at
    the code.  The point is still relevant, because I don't want to
    have to check the return code of close either.
      
This is kitchen sink type stuff.  I'm not sure what level of
implementation is required.  A general approach is to implement an
%ASSERT array like %SIG which would let users define handlers for
each operator, e.g. $ASSERT{open} = open_handler, with the default
being like most signals, death.  A simple solution is to define a single
boolean variable or command line arg for said selected set of operations. 
Either approach would go a long way towards more robust perl programs IMHO.

Another suggestion I have regards associative arrays.  Often I have an
array that needs to be accessed in two ways: chronologically and
associatively.  By chronologically, I mean the order in which the keys
were entered into the array.  The way I usually solve this is by
having two kinds of arrays: regular and premium.  This works, but as
has been mentioned in this newsgroup, is neither memory nor time
efficient.  This would be upwardly compatible with the "random order"
it returns now.  Looking at the code, I guess all one would have to
add is a next pointer to hentry.  Dbm files wouldn't be able to use 
this feature, but this isn't such a big deal.  I haven't had to use 
dbm files yet ;-)

Finally, I'd like better case-insensitive comparison support.  I like
//i, but I want ($a eq $b)i and sort nocase @a (or isort?).  I see
this as a completeness issue and not something critical.  [Note:
I haven't looked at this new comparison operator thingee which may
come in a case insensitive version.  If this is the case, this
suggestion is an elephant.]

BTW, my implementation of nocase looks like:
    local($A) = $a; $A =~ tr/A-Z/a-z/;
    local($B) = $b; $B =~ tr/A-Z/a-z/;
    $A eq $B ? 0 : $A lt $B ? -1 : +1;

Is there a simpler way to do this?  "(local($A) = $a) =~ ..."
certainly has undesirable effects.  For large lists, the extra copies
probably make the sort [much?] slower than a built-in nocase function.

All of these suggestions fall into *my* squeaky wheel category.  I
understand (all too well) the problem of language hacking: it never
stops.  This is not a Call For Implementation; it is an RFC.  I don't
think it's worth it to implement something unless there is
significant interest.  Furthermore, I don't like hacking in stuff
that won't be put in the "release"--too much local maintenance.

In <11232@jpl-devvax.JPL.NASA.GOV> Larry writes:
> You'll no doubt go and look at my sources, and discover that my header
> files don't include all their dependencies.  And they can't, because
> not everyone's header files are #ifdef'ed to avoid multiple inclusion yet.
> Maybe someday...

This is the primary reason we still use Modula-2: modules are handled
properly.  Well, actually, I do almost all of my programming in perl
these days... [flames to /dev/null]

Thanks for your comments.