=head1 TITLE
Overloadable && and ||
=head1 VERSION
Maintainer: Jean-Louis Leroy
Date: 04 Aug 2000
Version: 1
Mailing List: [EMAIL PROTECTED]
Number: 20
=head1 ABSTRACT
It should be possible to overload && and ||, for this has very
legitimate uses.
=head1 DISCUSSION
The reason often cited for not allowing the overloading of logical
junctions (i.e. && and ||, LJ for short) is that LJs are
'short-circuiting' operators, iow the second argument is not always
evaluated. User-defined LJs cannot benefit from this feature, and
making it possible to overload LJs would only result in confusion.
There are two arguments to the contrary.
Even without the conditional evaluation feature, there are
very legitimate uses for overloaded LJs. The arguments are not always
Perl expressions - they may be objects that participate in - for
example - abstract syntax trees.
An example of this can be found in Tangram, a persistence
facility. The following Perl code:
my $p = $storage->remote('NaturalPerson');
@results = $storage->select($p,
$p->{age} > 10 & $p->{age} < 20);
...gets translated to the following SQL code:
SELECT t1.id, t1.classId, t1.country, t1.address,
t2.age, t2.partner, t2.first_name, t2.name
FROM Person t1, NaturalPerson t2
WHERE (t2.age > 10 AND t2.age < 20) AND t2.id = t1.id
Note that the 'short-circuiting' behavior does occur, in a way: on the
database side. Also note that '&' has to be used instead of '&&',
because the latter is not overloadable. Using the more intuitive '&&'
silently results in incorrect code.
The second argument why overloadable LJs should be supported is that
it seems possible to make them enjoy the conditional evaluation of the
built-in LJs. When the compiler sees code like:
expr1 && expr2
...and detects that the LJ is overloaded, it could replace it with:
user_defined_and( sub { $expr1 }, sub { $expr2 } )
The user-defined '&&' can thus decide whether or not to evaluate its
operands, for example:
sub user_defined_and
{
# mimic built-in operator &&
my ($left, $right) = @_;
if (my $result = $left->())
{
return $result;
}
return $right->();
}