[% setvar title Replace invocant in @_ with self() builtin %]
Note: these documents may be out of date. Do not use as reference! |
To see what is currently happening visit http://www.perl6.org/
Replace invocant in @_ with self() builtin
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
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.
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.
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).
Replace the invocant usually included in $_[0] with self()
. Stop
passing the invocant in @_.
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.
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