Perl is worse!

Alex Martelli alex at magenta.com
Sat Jul 29 19:55:43 EDT 2000


"Steve Lamb" <grey at despair.rpglink.com> wrote in message
news:slrn8o6nub.f91.grey at teleute.rpglink.com...
    [snip]
> >As the 'behaving oddly' will typically produce irreversible alterations
> >of a precious persistent database
>
>     Only if you're typically working with persistent databases.

Which is what most computer work is doing, though the DB's may
not be relational ones.  Files, mailboxes, documents, saved
games, newsgroups, sites -- call them as you wish, they do
persist (hopefully:-) and your data are right there.


>     Personally, if my email client died because of some uncaught exception
> versus me being able to close out my message beacuse of some bug in a
display
> routine, I'd rather be able to close out and save my 20k message than have
to
> retype it.  There is more to programs than databases.

The crucial thing is that it must not mess up your mailbox and its
archives -- the rich, large, precious persistent database.  If it
does not keep a reasonably current copy of what you've typed so far
in a safe place on disk, it's junk anyway -- 20k worth of text is
likely to be *hours* of worth, and if they're kept in such a way
that a program crash makes you lose them, you'll also lose them if
electricity goes away, or the *OS* crashes (far from unknown, in
Microsoft widespread OS's especially), etc.

Losing one working-session, say several hours, is serious damage,
and clearly depends on a fundamentally wrong design of the program
that handles your work.  Losing a serious database, such as a full
mail archive, is utter tragedy -- the kind of thing that can break
a small company (if they haven't been religiously careful about
backing up *everything* frequently -- and far too many aren't).

A "small anomaly" that goes unnoticed (rather than triggering an
exception, that the programmer cannot ignore by default, but must
take a specific decision to catch somewhere) can corrupt the data
in ways that are subtle, hard to notice for a long time, and are
quite likely to degrade things.  A good example I've already seen
given to you is a program that's computing prices by multiplying
unit price, number of units, taxrate, discount, etc; if any one of
those, due to another bug, comes up as the string 'xyz', would
you rather the program took that as 0, and by multiplying get the
overall price as also zero, so the buyer can get the goods you're
selling at no cost at all?  Or would you rather get an unmistakable
exception just as soon as the wrong data is attempted to be taken
as a number?

Exceptions are your friends, because mistakes DO happen -- and
people writing programs never put in them ALL the checks they
should, if the default is that an error goes unnoticed.  With
exceptions, the default is a dramatic indication of the error,
so it DOES get handled -- not always WELL, mind you, since a
wilfully wrong-headed programmer can always deliberately choose
to catch and explicitly ignore them, but that requires a higher
order of perversity than the common mistake of failing to check
for each and every possible error!-)


> >Fortunately, it doesn't have to be made: wrapping the top-level entries
> >in a try/except is so TRIVIALLY easy, that there is really NO excuse
> >for any program not doing so.
>
>     Great, and then we're out of some other common practices.  CNTL-C, for
> example.  :P

Control-C (depending on the operating system) will cause a specific
exception, and the programmer decides how it gets handled.


> >but that does not stop ME from having a last will registered, nor
> >from wrapping my programs in try/except...:-).
>
>     Just out of curiousity, how do you get back down into the loop if it
is,
> say, 12 deep?  Does Python hit the handler, do its thing, drop back down?

No!  The semantics of 'restartable exceptions', which you refer to,
used to be very popular back when exceptions were first invented, but
turned out to be both extremely complex to implement correctly, AND
extremely complex to USE, so in practice there was really no pay-off
to the complexity.  Modern exception-systems are non-restartable:
once the stack is unwound all the way to an except clause that handles
the specific exception, execution continues right after that whole
try/except block.  I think the only restartable-exception you're at
all likely to encounter today (depending on what kind of work you do,
and on what platforms) is Win32's "Structured Error Handling" (SEH),
and even that is normally wrapped up into nonrestartable-exception
frameworks, such as C++'s (I'm not sure what Python does about SEH,
if indeed it does anything about it).

If the 12 nested loops must continue (which is infrequent: unhandled
exceptions mean unexpected errors, so the whole computation is most
likely junked), the try/except block must be at the lowest level.


> >Hey, you just *SAID* there could be a None, so you had NOT made
> >sure at all that they did contain numbers!  None is NOT a number.
> >The empty sequence is not a number.  You're contradicting yourself!
>
>     No, I made sure there was a number in there, Python is the one that
> decided to drop a None in.

That group did not match any part of the input string.  So, HOW did
you "make sure it contained a number"?!  no match -> empty sequence
(by default: you could have used the argument to groups to have no
match correspond to something else, but didn't, so accepting the
default of None).  An empty sequence is not a number.  So you did
NOT make sure the group contained a number!

You made sure it EITHER contained a sequence of digits, OR it did
not (and in this latter case it would contain None).  What's Python
got to do with it?!  What sequence of digits do you believe Python
could or should have possibly placed into a group that did not
match any part at all of your input string?!

Having chosen to place yourself in an either-or case (rather than
force both cases to uniformity through the argument to the groups
method), you then obviously have to handle each branch.  I've lost
count of the zillions of ways that have been suggested to you for
that purpose, from the plainest if/else, to try/except, to the
subtly elegant int(x or 0), etc, etc.  _These_ are all ways to
"make sure there's a number" (or, for try/except, you could frame
it as, assuming there is a number, but also handling the case
where there is not), just as the argument to groups is (in a
more wholesale way, rather than case-by-case).


Alex






More information about the Python-list mailing list