To use a $20 OO word, polymorphism. But this applies even if
$@ isn't an instance of an OO class, as explained herein.
If die/throw can put any data they want in $@, then before a
exception can be conditionally caught, the value of $@ must be
checked to see if it conforms to the intended check. For example,
if one user is allowed to die [ ... ]; and another user is allowed
to die { ... }; then catch clauses must be written like this.
catch ref $@ isa "HASH" && $@->{foo} => { ... }
catch ref $@ isa "ARRAY" && $@->[0] => { ... }
By placing some minimal structure on $@, say even a hash ref, catch
clauses can always be written like this
catch $@->{foo} => { ... }
because if any given die/throw doesn't set $@->{foo}, this still
works. That's a simple kind of polymorphism with a simple hash ref.
Now it takes no great insight that if $@ is going to be a hash ref,
then we can simply bless the hash into some class, say "Exception",
and then hang a bunch of convenience methods off the Exception::
namespace to avoid having a library version of the functions which
would pollute the namespace. And, it means we can write $@->foo,
instead of something like foo_exception($@), in catch clauses.
There you have it. That's why RFC 88 uses structured data for $@.
Now, here's an alternative that may keep everyone happy. In
addition to whatever RFC 88 does now, change this rule about how
die behaves:
If passed a single argument that isa "Exception", raise it as
the new exception and die in the fashion that Perl 5 does.
Otherwise, the arguments are stringified and joined with C<''>
(as in Perl 5), the resulting string is wrapped up in a new
Exception object (setting the message instance variable to said
string), and the new Exception object is raised.
to read like this:
If passed a single argument that isa "Exception", raise it as
the new exception and die in the fashion that Perl 5 does.
Otherwise, the arguments are stringified and joined with C<''>
(as in Perl 5), the resulting string is wrapped up in a new
Exception object (setting the message instance variable to said
string), the original unstringified arguments are saved in a
list ref in the object's C<args> instance variable, and the new
Exception object is raised.
then you can say C<die qw(A B C)>, and the following tests both work:
catch $@->args->[1] eq "B" => { ... }
catch $@ =~ /B/ => { ... }
Yours, &c, Tony Olekshy