[% setvar title Replace invocant in @_ with self() builtin %]

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

Replace invocant in @_ with self() builtin

VERSION

  Maintainer: Nathan Wiger <nate@wiger.org>
  Date: 24 Aug 2000
  Last Modified: 24 Sep 2000
  Mailing List: perl6-language-objects@perl.org
  Number: 152
  Version: 2
  Status: Frozen

ABSTRACT

Currently, the invocant is passed into a sub as the first element of @_, leading to the familiar construct:

   my $self = shift;

However, this is a big PITA. In particular, if you support several different calling forms (like CGI.pm), you have to check whether $_[0] is a ref or class name, etc.

This RFC, therefore, proposes a new builtin called self() which will return the correct invocant information. This has the added advantage that it is consistent with caller(), want(), <ref()>, and other context functions.

DESCRIPTION

Syntax

The new function self() would be called in the following way:

   sub fullname {
       my $self = self;
       @_ ? $self->{STATE}->{fullname} = $_[0]
          : $self->{STATE}->{fullname};
   }

   sub my_junk {
       my $this = self;
       $this->fork_o_matic(@_);
   }

   # Or even...

   sub error {
       carp @_ if self->config('VerboseErrors');
   }

   sub uid {
       @_ ? self->{uid} = $_[0]
          : self->{uid};
   }

The return value of self() would be similar to the current invocant in $_[0], with increased flexibility. In particular, it can be called anywhere and everywhere, not just within a method.

Depending on the context it's called in, the return value of self() will be:

   1. A reference to the object, within an object method

   2. The name of the package, within a package

   3. Undef, if a sub is not called as a method

These different return values give us the ability to call self() anywhere within Perl 6 code:

   package MyPackage;
   # ... many other functions ...
   sub do_stuff {
       print "Hello, @_" if self->config('Yep');
   }
   self->do_stuff;           # MyPackage->do_stuff

   package main;
   my $mp = new MyPackage;
   $mp->config('Yep') = 1;
   $mp->do_stuff('Nate');    # prints "Hello, Nate"

In addition, having a routine called self() has the major advantage that it hides the internal magic and scoping from the user. Just like using want() instead of a special variable called $WANT, self() makes using and comprehending contexts easy, simply changing the Perl 5 rule:

   "The invocant is passed into subs as $_[0] in OO contexts"

To the simpler still:

   "The invocant is always gotten by calling self()"

This provides a consistent interface, since self() can be called anywhere, just like caller(), want(), and other context functions.

Arguments against use invocant

This RFC was released prior to, and remains in opposition to, RFC 233, which proposes a use invocant pragma that provides the flexibility to name the invocant anything you want.

As many have noted, Perl is already hard enough. use invocant only gives us multiple ways to do something without adding value, only confusion, by promoting an inconsistent interface. Like providing a means to rename @ARGV and STDIN because a person prefers @args and output, use invocant further complicates an issue which should only be made easier.

The author of this RFC loves Perl and loves its flexibility. However, just like choosing a name for caller, want, print, @ARGV, and so forth, we need to choose a name for self as well to ease the burden on the programmer. "Choosing an interface" does not amount to "being un-Perlish" as some might purport to suggest. In fact, just the opposite: We're decreasing the amount of time a user has to spend decoding somebody else's invocant naming scheme by providing a very Perlishly-named function. This makes things easier.

If it is vital that the invocant must be named something specific, then a person can always use a sub wrapper, tie, or a typeglob to rename it appropriately. Actually, they don't even have to go to these extremes since they can still do this:

   sub getdata {
       my $this = self;
       return $this->{DATA}->{$_[0]};
   }

(that is, assign to a custom variable) anywhere they want to.

Finally, the author would be more than happy to settle for the selection of something different than self, such as this(), $SELF, or even $ME. The main point is that we need to choose something, because doing so makes the language more consistent and easier (combatting two widespread criticisms of Perl).

IMPLEMENTATION

Replace the invocant usually included in $_[0] with self(). Stop passing the invocant in @_.

MIGRATION

Backwards compatibility is simple. Subs can simply have the expression:

   unshift @_, self if self;

Added as the first line of the sub, since self() will return undef if not in an OO context.

REFERENCES

Critique of the use invocant pragma: www.mail-archive.com

Outline of the benefits of self: www.mail-archive.com

RFC 21: Replace wantarray with a generic want function

RFC 233: Objects: use invocant pragma