Inner functions and outer 'this' (Re: That hash symbol)

Allen Wirfs-Brock allen at wirfs-brock.com
Tue Mar 29 11:19:49 PDT 2011


On Mar 29, 2011, at 7:28 AM, David Herman wrote:

> On Mar 29, 2011, at 7:26 AM, David Herman wrote:
> 
>> This is what Sam is referring to -- we've been talking about exactly such a feature.
> 
> Sorry if that wasn't clear: at the last face-to-face we talked about allowing you to give your own custom name for the |this|-parameter, so that you could continue to refer to outer-bound |this|. This would use good ol' lexical scope, instead of exotic scope-crawling indices.

Yes, and there was considerable debate at the meeting on the desirability of the |this| solution (see Waldemar's notes) . ^this is an alternative proposal.

We probably need to directly compare the two and some of the objections to each.

Overview of proposals

this| - mandatory explicit naming of implicit this parameter

The original discussion in January added explicit naming and lexical scoping of the implicit "this" parameter to # function declarations.  In January we didn't settle on a syntax but in March we seem to be converging on something like:
   #foo(self | arg1, arg2) {...}
in the body of the above function, "self" would be bound to the implicit this parameter of the function and "this" would resolve to any lexically enclosing declarations of "this" or would be undefined if there were none.

It isn't clear whether or not arbitrary declarations of "this" would be allowed within such functions or whether "this" could only be bound in a "this |" context.

I believe that the intent of the proposal was that if you actually want to use "this" to refer to the implicit parameter you would have to explicitly declare it as:
   #foo(this | arg1, arg2) {...}
and that a declaration such as
   #foo( arg1, arg2) {...}
would not have a local binding for "this" and its implicit parameter would be inaccessible.

In the original discussion the "this|" declaration was only applied to  #-functions. All other function declaration forms would continue to reserve the meaning of "this" as a reference to the implicit parameter of the immediately enclosing function.

However, using the "this|" syntax it would probably be possible to extend the already existing function declaration forms:
   function foo(self | arg1) {};
   ({get prop(self |) {} })
   new Function("self | arg1", "return 42');
etc.
However for backwards compatibility, if the "|" was not present in these legacy forms they would have to fall back  to the legacy implicit this binding.

^this - explicit one-level outer this reference

In this proposal "^this" is a lexical token that may occurs as a PrimaryExpession.   It is interpreted as a reference to the implicit this parameter of  the outer function that immediately encloses the function body containing the "^this" token. In other words, it access the implicit this binding that is lexically one level further out than the current implicitly binding of "this".

It is a early error to use "^this" in any context where there isn't an outer function that encloses the the "^this" reference.

"this" remains a reserved word in all function declaration forms that refers to the implicit this parameter. It can not be used as the identifier in any declaration.

Pros and Cons for Each Proposal

this| Pros

It makes the implicit this parameter explicit.
Normal lexical scoping rules apply to "this".
It is similar to Python and perhaps other functional OO languages.
It allows arbitrary deep access to the implicit this parameter of outer functions.
It  takes a lexically scoped functional view rather than a OO view of methods.

this| Cons
It requires a new function declaration form.
The meaning of "this" will be different in functions declared using various forms.
Most methods only need the inner implicit this, yet they are forced to choose between:
   function() {}
   #(this|){}   //net saving only 4 chars.
Self-calls are no longer lexically explicit, you have to look at the function header to recognize one
Refactoring hazard when moving statements containing self-calls between methods.
It  is a solution that is more general than is needed to address the primary use cases at issue.
It remove "the this object" from the vocabulary for talking about  methods. What is the new terminology for the implicit method parameters?
It  takes a lexically scoped functional view rather than a OO view of methods.
 
^this Pros
It doesn't change anything about existing conventions for the implicit "this" parameter or "this" references.
It works equally well with both new and legacy function declaration forms
It address the primary use cases for outer this access without adding seldom needed generality
Consistency: "this" always means "this"; self-calls are always lexically explicit
It takes a classic OO view of methods .

^this Cons
Overloads "^" character; maintaining backwards compat with expressions like foo^this.bits would require parsing hackery.
May need to use "#this", "@this", or "#^this" instead.
It doesn't handle more than one level of function nesting.
It isn't like Python
It preserves the common OO language convention of implicitly naming the "receiver" parameter
It takes a classic OO view of methods.


I'll leave it to reader to weigh the above pros and cons.  But I do have a closing statement:

There is a decades long disagreement among designers/users of function and object-oriented languages.  OO proponents think there is something special about the "receiver" of a method call and that "self-calls" have special significance. This perspective pervasively colors OO software designs. Functional proponents (and while I'm happy to represent OO people,  I'm reluctant to put specific words into the broad group of  functional people) seem to view objects/methods as simply one of many abstractions than can be constructed out of higher-order functions.  They see little that is "special" about OO conventions and don't generally apply   OO software design techniques. 

JavaScript up to this point seems to have done a pretty good job of balancing the OO and functional perspective within the language. However, I think removing the specialness of "this" and the implicit this parameter may be a step too far that breaks that balance.  



More information about the es-discuss mailing list