[% setvar title Overloadable && and || %]

This file is part of the Perl 6 Archive

Note: these documents may be out of date. Do not use as reference!

To see what is currently happening visit http://www.perl6.org/


Overloadable && and ||


  Maintainer: Jean-Louis Leroy
  Date: 4 Aug 2000
  Mailing List: perl6-language@perl.org
  Number: 20
  Version: 1
  Status: Developing


It should be possible to overload && and ||, for this has very legitimate uses.


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->();