Proposal about the "self" keyword

Andrew Whitworth wknight8111 at gmail.com
Sun Feb 15 00:56:17 UTC 2009


On Sat, Feb 14, 2009 at 6:31 PM, Allison Randal <allison at parrot.org> wrote:
> Andrew Whitworth wrote:
>>
>> On Sat, Feb 14, 2009 at 4:21 PM, Allison Randal <allison at parrot.org>
>> wrote:
>>
>> Well, here's how I was thinking about it. We want the behavior between
>> various PMC types to be consistent. If we call
>>
>> $P0()
>>
>> Then "self" in the invoked routine should refer to $P0 here,
>> regardless of whether $P0 is a Sub, or a user-defined Object. When we
>> invoke something, "self" should be the object that is getting invoked
>> (or the object that is getting invoked upon).
>
> A keyword that gives you two completely different answers depending on how
> the code object was invoked ('self.$P1()' vs 'self()') is not consistent.
> It's problematic for code objects that can be invoked as both subs and
> methods. And, once there is a way to access the code object currently
> executing, I can guarantee people will want to use it in methods as well as
> sub (but won't be able to if it's accessed through 'self').

Okay, consider this code here:

$P0 = new "MyClass"
$P0."MyMeth"()
$P0()
...

.namespace ["MyClass"]

.sub invoke :vtable
   self               # What does this mean?
  ...
.end

.sub 'MyMeth'  :method
  self                # What does this mean?
  ...
.end

It makes sense to me that "self" in both those cases should be the
same thing: The PMC $P0. Now if we want to make these two different
because they mean different thigns, they should be given different
names. Given what we have above, what's really the difference between
these two instances:

$P0 = new 'MyClass'
$P1 = get_global 'MySub'
$P0()
$P1()

.sub 'MySub'
   ...
.end

.namespace ["MyClass"]

.sub 'Invoke' :vtable
   self           # refers to $P0 above
   ...
.end

Consider even that "MyClass" is an HLL mapped Sub type and it's
"invoke" override is analogous to the Code routine that a Sub PMC
points to when it's invoked. What's the real difference between these?
And if there is no real difference, why should one get "self" and the
other?

> Ah, well, we already have a solution for knowing whether optional parameters
> have been passed:
>
>  .param pmc self     :invocant :optional
>  .param int got_self :opt_flag
>
> (And if 'self' isn't marked as optional, then the .sub can *only* be called
> as a method.)

But :optional params can only be used at the end of an argument list.
At the very least it would require the parameter passing logic to be
reversed from what it currently is so that "self" is passed last
instead of passed first, and that would start getting in the way of
any other :optional parameters that other methods take.

>> As a side note, creating and using a "getself" opcode would actually
>> be a net win because we replace the current get_param/set_param pair
>> with a single "self = getself" op instead. Just a thought.
>
> I can see adding some sort of introspective ability to access the code
> object for the current sub/method that's executing. It would be useful in
> exception handlers too, to access the code object of the handler that's
> currently executing. But, it's not 'getself' because you're getting the code
> object, not the invocant. Call it something like 'get_current_sub'.

To my mind, these are the different cases that we would like to be
able to handle, and handle consistently

1) The invocant of a method call such as $P0 in $P0.'mymethod'()
2) The Object PMC that's involved in a normal :vtable call. So $P0 in:
$I0 = $P0, etc
3) The invoked Object PMC in an invoke VTABLE call. So $P0 in: $P0()
4) The current code object

There are probably more nuanced cases that I'm not thinking of. Now,
the three above could probably be turned into three separate keywords
("self", "object", and "code" at first pass), but then we look at
bizarre cases like this below:

$P0 = new 'MyClass'
$P0.'invoke'()
$P0()
$P1 = get_global ['MyClass'], 'invoke'
$P1()

.namespace ['MyClass']

.sub 'invoke' :method :vtable
   $P0 = self     # WTF?!?!?!
.end

And if we don't handle this in a way that's logical and consistent,
you can be sure that people are going to be using the various forms
listed above and will be confused as hell when the behavior of the
called Sub is different for each one.

--Andrew Whitworth


More information about the parrot-dev mailing list