On Mar 28, 2011, at 10:35 AM, Allen Wirfs-Brock <[email protected]> wrote:

> On Mar 27, 2011, at 11:13 AM, David Herman wrote:
> 
>> To be fair, your suggestion is more moderate than de Bruijn, although it's 
>> not clear whether you're proposing the ability to refer to shadowed bindings 
>> of *all* variables or just |this|. If it's the former, I'm *strongly* 
>> opposed. If it's the latter, well, I guess I'm still pretty opposed, just 
>> maybe less strongly. :)
> 
> 
> Dave, I think that applying this solution to the this-scoping issue may be a 
> really good idea
> 
> Claus, thanks from bringing a new (old) idea into the discussion.
> 
> I agree with Dave about all the fragility issues he mentioned for the general 
> case.  Also, I just don't see the general problem (if it is even a "problem") 
> as one that is important enough to try to "fix" in the language  since it is 
> probably rare and  it can be avoided by careful naming.
> 
> However, the specific case of 'this' is a different matter.    'this' is 
> implicitly rebound in every function scope and the JavaScript programmer has 
> no direct control over the naming and shadowing.  The result is that they 
> have to know and use the self renaming pattern.
> 
> This issue shows up enough in defining objects via object literal methods and 
> in methods that call higher order functions that it is something that may 
> well be worth addressing in the language.  Particularly as we discuss adding 
> additional declarative forms to Harmony that included nested method 
> definitions.  The outer 'this' problem is limited enough that we can avoid 
> things like dynamic scoping complications in the solution.  Also it is 
> limited enough that I don't believe that the solution imposes refactoring 
> complications.  
> 
> Here is a sketch of a proposal:
> 
> ^this is added as a new lexical token of the language. When spoken it is 
> pronounced as "outer this" .  In the expression grammar ^this is a primary 
> expression.
> 
> It is a syntax error for ^this to appear outside of a function body.  It may 
> not occur at the top level of a program.  
> 
> When evaluated, the value of ^this is the this binding of the function that 
> immediately lexically encloses the function body that contains the ^this.  It 
> is a early syntax error if there is no such function.  For example:
> 
> //at the top level
> var self = ^this;  //syntax error, at the top level
> function foo() {
>   ^this.bar();  //syntax error, no enclosing function
> }
> 
> The two primary  use cases for ^this are exemplified by the following two 
> examples:
> 
> MyObj.prototype.addClickHandingForElement(elem) {
>   elem.addEventListener('click', function (e) {^this.handleClick(this,e)});
> }
This does provide an elegant solution but perhaps for a somewhat uncommon 
problem. Today I think most would do the following (if not using self):
MyObj.prototype.addClickHandingForElement(elem) {
elem.addEventListener('click', this.handleClick.bind(this))
}
Where the event.target would be used in the context of handleclick. I've 
noticed that coffescript uses this=> to autobind but not disambiguate. One 
possible alternative would be to have a keyword modifier similar to your 
suggested method called "callback" which autobinds this. From a declarative 
viewpoint it would be clear what methods within the type were intended to be 
used in this way. Although it would not handle the inner outer this use case. 
Your second example below I would of done as:

MyObj.prototype.wrap = (function (wrapper) {
  // create a wrapper object that limits access to the properties of one of my 
objects
  return {
       name: this.id,  //fix name of wrapper at creation (uses this of wrap call
       get foo () {return wrapper.foo},  //outer this is this of wrap call
      set bar(val) {wrapper.bar = val}  //outer this is this of wrap call  
})(this);

even if ^this were available since I would find it clearer. At least in my 
experience I do not run into many scenarios where both this and ^this are 
accessed in the same context, but I do use/find many scenarios where callbacks 
should be bound especially when custom events are used liberally or within 
node. In those cases where I need both I tend to curry the inner this and 
provide it as a parameter to the outer callback. Somewhat contrived for the 
first example since elem is available in the event but it would look like
elem.addEventListener('click', this.handleClick.bind(this).curry(elem))
assuming curry was available on the Function prototype.


> 
> MyObj.prototype.wrap = function () {
>   // create a wrapper object that limits access to the properties of one of 
> my objects
>   return {
>        name: this.id,  //fix name of wrapper at creation (uses this of wrap 
> call
>        get foo () {return ^this.foo},  //outer this is this of wrap call
>        set bar(val) {^this.bar = val}  //outer this is this of wrap call  
> }
> 
> Note that only one level outer this access is supported, ^^this would be a 
> syntax error.  In the rare cases where somebody really needs deeper access to 
> shadowed this binding then they can fall back to the self pattern. 
> 
> I see minimal refactoring hazards here as the outer scope reference is 
> limited to one level, is  explicitly marked at the usage site, and only 
> applies to this.
> 
> Possible reservations: 
> This use of ^ probably would preclude its use as a short form of the 'return' 
> keyword (for those people who aren't in favor of adding implicit returns).
> It looks odd to old Smalltalk programmers.
> 
> Overall, I really like ^this as a narrow solution to a specific real usage 
> problem. I'm interested in reactions and unless somebody thinks of something 
> that seriously torpedoes it I will probably write it up as a strawman. 
> 
> Allen
> _______________________________________________
> es-discuss mailing list
> [email protected]
> https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to