[% setvar title Objects: C pragma %]

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/

TITLE

Objects: use invocant pragma

VERSION

  Maintainer: Damian Conway <damian@conway.org>
  Date: 14 Sep 2000
  Last Modified: 25 Sep 2000
  Mailing List: perl6-language@perl.org
  Number: 223
  Version: 2
  Status: Frozen

ABSTRACT

This RFC proposes that, as in Perl 5, the invocant of a method should be normally available to the method as $_[0], but that it can be automaticaly stripped from @_ and accessed via either a subroutine or a variable, using the use invocant pragma.

DESCRIPTION

It is proposed that Perl 6 methods continue to receive their invocant (i.e. a reference to the object on which they were invoked) via $_[0].

This mechanism has served Perl 5 well and preserving it as the default will greatly simplify migration of OO Perl code.

It is, however, tedious that all Perl methods are thereby forced to start with:

	sub method {
		my ($self, @args) = @_;
		...
	}

or its various moral equivalents.

The problem may be eased somewhat in Perl 6, if methods can have proper parameter lists:

	sub method ($self, @args) {
		...
	}

and this may, indeed, be sufficient.

However, it might also be useful if the invocant could be passed to a method via an entirely separate mechanism -- either a magic variable, or a magic subroutine.

The problem is: how to avoid the religious wars over which of these two alternative mechanisms is better, and what the chosen mechanism should be called.

It is therefore proposed that Perl 6 provide a pragma -- invocant -- that takes the name of either a scalar variable or a subroutine and causes that variable or subroutine to evaluate to the invocant of any method within the lexical scope of the pragma. Furthermore, where the pragma is in effect, methods would not receive their invocant as $_[0].

For example:

	use invocant '$ME';

	sub method {
		$ME->{calls}++;
		$ME->SUPER::method(@_);
	}

or:

	use invocant 'self';

	sub method {
		self->{calls}++;
		self->SUPER::method(@_);
	}

Note that there is no need to shift @_ before passing it to the ancestral method, since the invocant is not prepended to the argument list in the first place.

MIGRATION ISSUES

None. That's the point.

IMPLEMENTATION

Pragma adds a trivial wrapper around affected methods. For example:

	use invocant '$ME';

	sub method {
		$ME->{calls}++;
		$ME->SUPER::method(@_);
	}

becomes:

	sub method {
	    my $ME = shift;
	    do {
		$ME->{calls}++;
		$ME->SUPER::method(@_);
	    }
	}

whilst:

	use invocant 'self';

	sub method {
		self->{calls}++;
		self->SUPER::method(@_);
	}

becomes:

	sub method {
	    local *self = do { my $_invocant = shift; sub { $_invocant } };
	    do {
		self->{calls}++;
		self->SUPER::method(@_);
	    }
	}

REFERENCES

RFC 128 : Subroutines: Extend subroutine contexts to include name parameters and lazy arguments

RFC 137 : Overview: Perl OO should not be fundamentally changed.

RFC 152 : Replace invocant in @_ with self() builtin