[Israel.pm] List of all contexts in Perl

Mikhael Goikhman migo at homemail.com
Sun May 30 03:32:13 PDT 2010


On 30 May 2010 12:09:52 +0300, Offer Kaye wrote:
> 
> I'm not sure I understand what "boolean context" means, or any of the
> others you listed. Except for the ".." operator does any of Perl's
> built-in functions operate differently inside an "if" test for
> example, in terms of the value returned (assuming you assign it to
> something)?
> 
> Looked at another way, you can do anything you want with the return
> value of for example "localtime", but in the end it will still return
> either a scalar or list, regardless of what you do with those values
> later on, right?

In fact localtime works differently under scalar, boolean (works like
numerical here) and list contexts. Run this if you don't believe me:

	perl -le 'print scalar localtime'
	perl -le 'print int localtime'
	perl -le 'print localtime == 0 ? "TRUE" : "FALSE"'
	perl -le 'print join ", ", localtime'

But most of other built-in functions may work the same under numeric,
scalar, boolean or say dereferencing contexts. This does not mean
these contexts do not exist. :)

Example. In Podius projects there are objects of super class
Podius::Component. They define own stringification:

	use overload '""' => "as_string";

	# just an example implementation
	sub as_string ($) {
		my $self = shift; 

		my $type = $self->get_type;
		my $id = $self->get_id;

		return "[$type, $id]";
	}

Then if someone uses such object in string "Bought: $book" he gets
"Bought: [AtlasBook, 123001]" and not
"Bought: Podius::Component::AtlasBook=ARRAY(0x9abcdef)".

But then, if we defined the scalar conversion for some class, it may
be used in place of numeric conversion. By default when you use
int($book) you get this 0x9abcdef address in decimal. This may be
useful (say to distinuguish between different revisions of the same
object in memory when implementing merge of concurrent changes to the
same persistent object). So let's define the numberic conversion too:

	use overload '0+' => "get_transient_id";

	# just an example implementation, not really important for us
	sub get_transient_id ($) {
		my $self = shift; 

		my $ref = ref($self);
		throw("get_transient_id: no object") unless $ref;
		bless $self, 'overload::Fake';
		my $transient_id = int($self);
		bless $self, $ref;

		return $transient_id;
	}

But then if we defined this numeric conversion, it will be used in
boolean context too (the conversion hierarchies are defined by perl).
And this numberic conversion is slow with all these reblessings. You
just want it to be fast when you write: if ($book) { "work-with-it" }
So let's just make it as fast as possible:

	use overload 'bool' => sub { 1 };

You can go even further with this. For example for Book you can
define the operation of dereferincing to array as some division to
Page objects (just an example), so you can do: my $pages = @$book;
(yes, it is intended to return ARRAY reference, not list).

	use overload '@{}' => 'some_interesting_method';

I hope these real life examples may help to see when scalar, numeric
and boolean (or even dereferencing) contexts are used/useful.

Regards,
Mikhael.

-- 
perl -e 'print+chr(64+hex)for+split//,d9b815c07f9b8d1e'


More information about the Perl mailing list