[Prototype-core] Re: A more efficient $super for Prototype 2

2009-09-09 Thread Jim Higson

On Tuesday 08 September 2009 16:18:20 T.J. Crowder wrote:
 @Jim,

  Ie, Class.create takes any number of objects of functions or functions.
  If functions, the function name is used.

 I see where you're coming from, but FWIW I'm with Allen on this one.
 Also, there's no standard way to get the name of a function until
 ECMAScript5 (which standardizes the truly outrageous idea that
 function instances should have -- gasp! -- a name property), and at
 the moment although Firefox 3.5, Chrome 2, and Safari 4 all already
 have that property, IE7 (at least, haven't tested IE8) and Opera10 do
 not.

I have a hunch we could get function names in the same way that we implement 
Function#argumentNames. A regex on the toString.

-- 
Jim
my wiki ajaxification thing: http://wikizzle.org
my blog: http://jimhigson.blogspot.com/

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Prototype: Core group.
To post to this group, send email to prototype-core@googlegroups.com
To unsubscribe from this group, send email to 
prototype-core-unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/prototype-core?hl=en
-~--~~~~--~~--~--~---



[Prototype-core] Re: A more efficient $super for Prototype 2

2009-09-09 Thread Jim Higson

On Wednesday 09 September 2009 09:02:28 Jim Higson wrote:

  I see where you're coming from, but FWIW I'm with Allen on this one.
  Also, there's no standard way to get the name of a function until
  ECMAScript5 (which standardizes the truly outrageous idea that
  function instances should have -- gasp! -- a name property), and at
  the moment although Firefox 3.5, Chrome 2, and Safari 4 all already
  have that property, IE7 (at least, haven't tested IE8) and Opera10 do
  not.

 I have a hunch we could get function names in the same way that we
 implement Function#argumentNames. A regex on the toString.

I should have looked first - this is function decompilation and considered a 
bad thing.

-- 
Jim
my wiki ajaxification thing: http://wikizzle.org
my blog: http://jimhigson.blogspot.com/

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Prototype: Core group.
To post to this group, send email to prototype-core@googlegroups.com
To unsubscribe from this group, send email to 
prototype-core-unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/prototype-core?hl=en
-~--~~~~--~~--~--~---



[Prototype-core] Re: A more efficient $super for Prototype 2

2009-09-09 Thread T.J. Crowder

Hi all,

I thought of a wrinkle today:  Mixins.  This new mechanism modifies
function instances if they override base class functions (it leaves
them alone if they don't).  So if you mix in something that has a
function with the same name as a parent class's function, we will set
a $super property on the mixin function's instance.  That seems wrong
to me, mixins should be read-only as far as the mechanism is
concerned, IMHO.

Now, in _practical_ terms, unless the mixin function calls $super
(which seems an odd thing for a mixin to do, but I can come up with an
edge case use case for it), it doesn't matter much.  But if A) the
mixin function does (presumably optionally) call $super, and B) more
than one class mixes the mixin in, AND C) the mixin overrides one of
the functions in at least one of those classes, you get class
crosstalk -- a very bad thing.

My first thought for how to deal with this was stupid and I'll spare
you.

My *second* (hopefully not stupid) thought was to mark mixin functions
with a property telling us to leave them alone.  I see two
ramifications to doing that:

1. An API change:  To define a mixin, you'd ideally want to run it
through something (something we'd presumably provide) that spins
through and marks the functions so we leave them alone.

var MyMixIn = Class.createMixin(...);

2. Mixins can't even optionally participate in supercalls, which they
can with the current mechanism.

Now, for me, #2 is not a problem.  I'm not thrilled about introducing
#1, although really you only have to do that to protect against an
edge case you're probably not going to run into.  It's someting a
library of mixins would want to be sure to do, but within a non-
library project, not sure it really matters.

-- T.J.

On Sep 9, 9:28 am, Jim Higson j...@wikizzle.org wrote:
 On Wednesday 09 September 2009 09:02:28 Jim Higson wrote:

   I see where you're coming from, but FWIW I'm with Allen on this one.
   Also, there's no standard way to get the name of a function until
   ECMAScript5 (which standardizes the truly outrageous idea that
   function instances should have -- gasp! -- a name property), and at
   the moment although Firefox 3.5, Chrome 2, and Safari 4 all already
   have that property, IE7 (at least, haven't tested IE8) and Opera10 do
   not.

  I have a hunch we could get function names in the same way that we
  implement Function#argumentNames. A regex on the toString.

 I should have looked first - this is function decompilation and considered a
 bad thing.

 --
 Jim
 my wiki ajaxification thing:http://wikizzle.org
 my blog:http://jimhigson.blogspot.com/
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Prototype: Core group.
To post to this group, send email to prototype-core@googlegroups.com
To unsubscribe from this group, send email to 
prototype-core-unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/prototype-core?hl=en
-~--~~~~--~~--~--~---



[Prototype-core] Re: A more efficient $super for Prototype 2

2009-09-09 Thread Allen Madsen

TJ,

I don't particularly think this is a problem or even a new problem
(wouldn't the current let you do this as well?). This sounds like
protecting the developer from themselves. I think as long as you
sufficiently state what will happen in a particular instance then it
is perfectly reasonable to allow each individual developer to handle
it as they see fit.

Allen Madsen
http://www.allenmadsen.com



On Wed, Sep 9, 2009 at 7:29 AM, T.J. Crowdert...@crowdersoftware.com wrote:

 Hi all,

 I thought of a wrinkle today:  Mixins.  This new mechanism modifies
 function instances if they override base class functions (it leaves
 them alone if they don't).  So if you mix in something that has a
 function with the same name as a parent class's function, we will set
 a $super property on the mixin function's instance.  That seems wrong
 to me, mixins should be read-only as far as the mechanism is
 concerned, IMHO.

 Now, in _practical_ terms, unless the mixin function calls $super
 (which seems an odd thing for a mixin to do, but I can come up with an
 edge case use case for it), it doesn't matter much.  But if A) the
 mixin function does (presumably optionally) call $super, and B) more
 than one class mixes the mixin in, AND C) the mixin overrides one of
 the functions in at least one of those classes, you get class
 crosstalk -- a very bad thing.

 My first thought for how to deal with this was stupid and I'll spare
 you.

 My *second* (hopefully not stupid) thought was to mark mixin functions
 with a property telling us to leave them alone.  I see two
 ramifications to doing that:

 1. An API change:  To define a mixin, you'd ideally want to run it
 through something (something we'd presumably provide) that spins
 through and marks the functions so we leave them alone.

    var MyMixIn = Class.createMixin(...);

 2. Mixins can't even optionally participate in supercalls, which they
 can with the current mechanism.

 Now, for me, #2 is not a problem.  I'm not thrilled about introducing
 #1, although really you only have to do that to protect against an
 edge case you're probably not going to run into.  It's someting a
 library of mixins would want to be sure to do, but within a non-
 library project, not sure it really matters.

 -- T.J.

 On Sep 9, 9:28 am, Jim Higson j...@wikizzle.org wrote:
 On Wednesday 09 September 2009 09:02:28 Jim Higson wrote:

   I see where you're coming from, but FWIW I'm with Allen on this one.
   Also, there's no standard way to get the name of a function until
   ECMAScript5 (which standardizes the truly outrageous idea that
   function instances should have -- gasp! -- a name property), and at
   the moment although Firefox 3.5, Chrome 2, and Safari 4 all already
   have that property, IE7 (at least, haven't tested IE8) and Opera10 do
   not.

  I have a hunch we could get function names in the same way that we
  implement Function#argumentNames. A regex on the toString.

 I should have looked first - this is function decompilation and considered a
 bad thing.

 --
 Jim
 my wiki ajaxification thing:http://wikizzle.org
 my blog:http://jimhigson.blogspot.com/
 


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Prototype: Core group.
To post to this group, send email to prototype-core@googlegroups.com
To unsubscribe from this group, send email to 
prototype-core-unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/prototype-core?hl=en
-~--~~~~--~~--~--~---



[Prototype-core] Re: A more efficient $super for Prototype 2

2009-09-09 Thread Robert Kieffer
I'm with Allen on this.  I don't think it's uncommon for mixins to want to
hook into existing functionality.  This is trivial if they can invoke $super
(the original object's method), and problematic otherwise.

To give a concrete example, a while ago I implemented a Selectable mixin
for some collection classes.  Because this mixin maintained the selection
state in a private cache, it needed to hook into the remove() method to
allow it to properly update the cache.  Thus, I could easily see doing
something like this:

var Selectable = Class.createMixin({
  // Various methods we add to the collection class...
  selectItem: function(item){...},
  deselectItem:function(item){...},
  getSelectedItems: function() {...},

  // Make sure we deselect items before they're removed
  remove: function($super, item) {
this.deselectItem(item);
$super(item);
  }
})

On Wed, Sep 9, 2009 at 7:31 AM, Allen Madsen bla...@gmail.com wrote:


 TJ,

 I don't particularly think this is a problem or even a new problem
 (wouldn't the current let you do this as well?). This sounds like
 protecting the developer from themselves. I think as long as you
 sufficiently state what will happen in a particular instance then it
 is perfectly reasonable to allow each individual developer to handle
 it as they see fit.

 Allen Madsen
 http://www.allenmadsen.com



--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Prototype: Core group.
To post to this group, send email to prototype-core@googlegroups.com
To unsubscribe from this group, send email to 
prototype-core-unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/prototype-core?hl=en
-~--~~~~--~~--~--~---



[Prototype-core] Re: A more efficient $super for Prototype 2

2009-09-09 Thread T.J. Crowder

Hi Allen,

Thanks.  I agree, it's a very edgy edge case. :-)

 (wouldn't the current let you do this as well?)

Actually, it works in the current implementation, because if a mixin
function uses $super (which again is a bit odd), addMethods wraps it
up in a closure and never modifies the actual function.  The closure
is specific to the subclass, and so it all Just Works.

-- T.J.

On Sep 9, 3:31 pm, Allen Madsen bla...@gmail.com wrote:
 TJ,

 I don't particularly think this is a problem or even a new problem
 (wouldn't the current let you do this as well?). This sounds like
 protecting the developer from themselves. I think as long as you
 sufficiently state what will happen in a particular instance then it
 is perfectly reasonable to allow each individual developer to handle
 it as they see fit.

 Allen Madsenhttp://www.allenmadsen.com



 On Wed, Sep 9, 2009 at 7:29 AM, T.J. Crowdert...@crowdersoftware.com wrote:

  Hi all,

  I thought of a wrinkle today:  Mixins.  This new mechanism modifies
  function instances if they override base class functions (it leaves
  them alone if they don't).  So if you mix in something that has a
  function with the same name as a parent class's function, we will set
  a $super property on the mixin function's instance.  That seems wrong
  to me, mixins should be read-only as far as the mechanism is
  concerned, IMHO.

  Now, in _practical_ terms, unless the mixin function calls $super
  (which seems an odd thing for a mixin to do, but I can come up with an
  edge case use case for it), it doesn't matter much.  But if A) the
  mixin function does (presumably optionally) call $super, and B) more
  than one class mixes the mixin in, AND C) the mixin overrides one of
  the functions in at least one of those classes, you get class
  crosstalk -- a very bad thing.

  My first thought for how to deal with this was stupid and I'll spare
  you.

  My *second* (hopefully not stupid) thought was to mark mixin functions
  with a property telling us to leave them alone.  I see two
  ramifications to doing that:

  1. An API change:  To define a mixin, you'd ideally want to run it
  through something (something we'd presumably provide) that spins
  through and marks the functions so we leave them alone.

     var MyMixIn = Class.createMixin(...);

  2. Mixins can't even optionally participate in supercalls, which they
  can with the current mechanism.

  Now, for me, #2 is not a problem.  I'm not thrilled about introducing
  #1, although really you only have to do that to protect against an
  edge case you're probably not going to run into.  It's someting a
  library of mixins would want to be sure to do, but within a non-
  library project, not sure it really matters.

  -- T.J.

  On Sep 9, 9:28 am, Jim Higson j...@wikizzle.org wrote:
  On Wednesday 09 September 2009 09:02:28 Jim Higson wrote:

I see where you're coming from, but FWIW I'm with Allen on this one.
Also, there's no standard way to get the name of a function until
ECMAScript5 (which standardizes the truly outrageous idea that
function instances should have -- gasp! -- a name property), and at
the moment although Firefox 3.5, Chrome 2, and Safari 4 all already
have that property, IE7 (at least, haven't tested IE8) and Opera10 do
not.

   I have a hunch we could get function names in the same way that we
   implement Function#argumentNames. A regex on the toString.

  I should have looked first - this is function decompilation and considered 
  a
  bad thing.

  --
  Jim
  my wiki ajaxification thing:http://wikizzle.org
  my blog:http://jimhigson.blogspot.com/
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Prototype: Core group.
To post to this group, send email to prototype-core@googlegroups.com
To unsubscribe from this group, send email to 
prototype-core-unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/prototype-core?hl=en
-~--~~~~--~~--~--~---



[Prototype-core] Re: A more efficient $super for Prototype 2

2009-09-09 Thread kangax



On Sep 9, 7:29 am, T.J. Crowder t...@crowdersoftware.com wrote:
 Hi all,

 I thought of a wrinkle today:  Mixins.  This new mechanism modifies
 function instances if they override base class functions (it leaves
 them alone if they don't).  So if you mix in something that has a
 function with the same name as a parent class's function, we will set
 a $super property on the mixin function's instance.  That seems wrong
 to me, mixins should be read-only as far as the mechanism is
 concerned, IMHO.

 Now, in _practical_ terms, unless the mixin function calls $super
 (which seems an odd thing for a mixin to do, but I can come up with an
 edge case use case for it), it doesn't matter much.  But if A) the
 mixin function does (presumably optionally) call $super, and B) more
 than one class mixes the mixin in, AND C) the mixin overrides one of
 the functions in at least one of those classes, you get class
 crosstalk -- a very bad thing.

 My first thought for how to deal with this was stupid and I'll spare
 you.

 My *second* (hopefully not stupid) thought was to mark mixin functions
 with a property telling us to leave them alone.  I see two
 ramifications to doing that:

Well, technically mixins are already marked by being an object,
rather than a function :)

// Constructor/Class (a function)
function Person(){}

// Mixin (not a function, although it could be (!))
var Observable = {
  observe: function(){ ... },
  stopObserving: function(){ ... }
}

I don't think there was ever such requirement for mixins in Prototype,
though, so there's a chance people are using function-based mixins
(for whatever reasons):

function Observable(){ ... };

Object.extend(Observable, {
  observe: function(){ ... },
  stopObserving: function(){ ... }
});

[...]

--
kangax
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Prototype: Core group.
To post to this group, send email to prototype-core@googlegroups.com
To unsubscribe from this group, send email to 
prototype-core-unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/prototype-core?hl=en
-~--~~~~--~~--~--~---



[Prototype-core] Re: A more efficient $super for Prototype 2

2009-09-09 Thread T.J. Crowder

Hi Robert,

That's a very interesting use case, thanks for that.  I can certainly
see the utility of that, and in fact as I was writing all of this up
for my (pathetic little) blog I was getting increasingly uncomfortable
with the mixin issue.

If it's important for mixins to participate in hierarchy, it occurs to
me that my second point (saying they can't) is unduly pessimistic.  Of
course they can.  Unlike subclass methods, it's important that we
don't modify them directly, but that doesn't mean they can't play.  In
this one special case where we basically have no choice, we can allow
ourselves the indirection and wrap them, modifying the wrapper rather
than the original.  That costs a closure per mixin method (not on
every call, just at mixin-time), and then an extra #apply on each
mixin call.  Still much more efficient than what we currently have,
and it keeps mixins fully able to participate in the hierarchy.

That's much more satisfying that shutting them out (and potentially
breaking the chain).

Thanks again,

-- T.J.

On Sep 9, 4:00 pm, Robert Kieffer bro...@gmail.com wrote:
 I'm with Allen on this.  I don't think it's uncommon for mixins to want to
 hook into existing functionality.  This is trivial if they can invoke $super
 (the original object's method), and problematic otherwise.

 To give a concrete example, a while ago I implemented a Selectable mixin
 for some collection classes.  Because this mixin maintained the selection
 state in a private cache, it needed to hook into the remove() method to
 allow it to properly update the cache.  Thus, I could easily see doing
 something like this:

 var Selectable = Class.createMixin({
   // Various methods we add to the collection class...
   selectItem: function(item){...},
   deselectItem:function(item){...},
   getSelectedItems: function() {...},

   // Make sure we deselect items before they're removed
   remove: function($super, item) {
     this.deselectItem(item);
     $super(item);
   }



 })
 On Wed, Sep 9, 2009 at 7:31 AM, Allen Madsen bla...@gmail.com wrote:

  TJ,

  I don't particularly think this is a problem or even a new problem
  (wouldn't the current let you do this as well?). This sounds like
  protecting the developer from themselves. I think as long as you
  sufficiently state what will happen in a particular instance then it
  is perfectly reasonable to allow each individual developer to handle
  it as they see fit.

  Allen Madsen
 http://www.allenmadsen.com
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Prototype: Core group.
To post to this group, send email to prototype-core@googlegroups.com
To unsubscribe from this group, send email to 
prototype-core-unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/prototype-core?hl=en
-~--~~~~--~~--~--~---



[Prototype-core] Re: A more efficient $super for Prototype 2

2009-09-08 Thread Jim Higson

On Tuesday 08 September 2009 03:57:13 Allen Madsen wrote:
 TJ,
 I guess I don't understand why it wouldn't work. I'll illustrate how I
 understand it and you correct me where I'm wrong.

 var A = Class.create({
   nifty: function(){}
 });

 var B = Class.create(A, {
   nifty: function(){
 this.nifty.$super(); // refers to A.nifty()
 //this.nifty(); //would cause recursion
   }
 });

Wouldn't you have to do this to preserve scope?

this.nifty.$super.call( this );

Myself, I've never liked the .call syntax much because I mistake it with 
apply: the two words seem arbitrary. But, yeah, I can see that pre-binding 
every overridden method of every object would be a big overhead.

Perhaps I would do:

var B = Class.create(A, {
  nifty: function(){

var $super = this.nifty.$super.bind( this );
// $super refers to A.nifty() bound to this
$super();
  }
});

[1] Please correct if this is wrong!

-- 
Jim
my wiki ajaxification thing: http://wikizzle.org
my blog: http://jimhigson.blogspot.com/

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Prototype: Core group.
To post to this group, send email to prototype-core@googlegroups.com
To unsubscribe from this group, send email to 
prototype-core-unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/prototype-core?hl=en
-~--~~~~--~~--~--~---



[Prototype-core] Re: A more efficient $super for Prototype 2

2009-09-08 Thread T.J. Crowder

Hi Jim,

 Perhaps I would do:

 var B = Class.create(A, {
   nifty: function(){

 var $super = this.nifty.$super.bind( this );
 // $super refers to A.nifty() bound to this
 $super();
   }

 });

 [1] Please correct if this is wrong!

You need to leave out the this. and use a named function instead;
see my note to Allen for the details.  You can use #bind if you want
to, but in my experience you're typically only making a single call to
the superclass method, so it's not really worth the overhead.  But
here's what it would look like:

var B = Class.create(A, (function(){

  function nifty(){
var $super = nifty.$super.bind( this );
// $super refers to A.nifty() bound to this
$super();
  }

  return {nifty: nifty};
})());

-- T.J.

On Sep 8, 8:52 am, Jim Higson j...@wikizzle.org wrote:
 On Tuesday 08 September 2009 03:57:13 Allen Madsen wrote:

  TJ,
  I guess I don't understand why it wouldn't work. I'll illustrate how I
  understand it and you correct me where I'm wrong.

  var A = Class.create({
    nifty: function(){}
  });

  var B = Class.create(A, {
    nifty: function(){
      this.nifty.$super(); // refers to A.nifty()
      //this.nifty(); //would cause recursion
    }
  });

 Wouldn't you have to do this to preserve scope?

 this.nifty.$super.call( this );

 Myself, I've never liked the .call syntax much because I mistake it with
 apply: the two words seem arbitrary. But, yeah, I can see that pre-binding
 every overridden method of every object would be a big overhead.

 Perhaps I would do:

 var B = Class.create(A, {
   nifty: function(){

     var $super = this.nifty.$super.bind( this );
     // $super refers to A.nifty() bound to this
         $super();
   }

 });

 [1] Please correct if this is wrong!

 --
 Jim
 my wiki ajaxification thing:http://wikizzle.org
 my blog:http://jimhigson.blogspot.com/
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Prototype: Core group.
To post to this group, send email to prototype-core@googlegroups.com
To unsubscribe from this group, send email to 
prototype-core-unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/prototype-core?hl=en
-~--~~~~--~~--~--~---



[Prototype-core] Re: A more efficient $super for Prototype 2

2009-09-08 Thread Radoslav Stankov

It really looks nicer :)

I was generally using this.constructor ... and so on. But this is
better. I haven't run it but I guest it is possible to do

this.method.$super.call(this, ...)
arguments.callee.$supper.call(this, ...)

Witch is nice.
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Prototype: Core group.
To post to this group, send email to prototype-core@googlegroups.com
To unsubscribe from this group, send email to 
prototype-core-unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/prototype-core?hl=en
-~--~~~~--~~--~--~---



[Prototype-core] Re: A more efficient $super for Prototype 2

2009-09-08 Thread Richard Quadling

2009/9/8 T.J. Crowder t...@crowdersoftware.com:

 Hi all,

 I've taken a break from porting documentation from Mephisto into the
 source (zz) to do a first take on implementing the new
 supercalls!  Here's the commit in a branch in my repo:[1]

 That commit includes the code, documentation, and unit tests. The old
 class unit tests are still there (I've just renamed them oldclass,
 though not properly from a git history POV I just realized) so we
 continue to test the old style until we remove it, which I would
 assume would be a couple of versions after introducing the new one.
 I've also added tests to prove that you can mix the two styles (derive
 from an old-style using the new style, or vice-versa), not that I
 recommend doing that. Apologies in advance if I'm out on a limb
 stylistically; I tried to fit in (inline vars! yuck!). If I've gone
 astray, please let me know.

 As you can see, the implementation in the Prototype code is dead
 simple, and yet the new supercalls are easy to use, particularly if
 you're already sold on the benefits of using named rather than
 anonymous functions (or if you don't care how phenomenally slow
 `arguments.callee` is).

 This gist[2] contains a basic performance comparison page.  The change
 really is dramatic, even if you use arguments.callee -- but it's mind-
 blowing if you use named functions (thanks, kangax, for pointing that
 out!).

 About dynamism:  Coming from the compiled language world, I would
 never have thought to handle people adding methods to classes on-the-
 fly AFTER the class may have been derived; thank you to Tobie for
 pointing out that requirement.  The code correctly handles defining
 new methods and redefining methods, ensuring that everybody is linked
 up correctly.  (That turned out to be trivial.)  But I have a couple
 of questions for you dynamic types:

 1) Does it need to support _removing_ a method entirely? (Currently
 does not; easy to add.)

 2) Does it need to handle edge cases where a name is defined on
 classes but is not a function (e.g., a class variable), but then we
 REdefine it to be a function? Or vice-versa (replacing a function with
 a non-function)? (Currently does not handle it; will complicate the
 code somewhat.)

 I can just about imagine (1), but frankly if you're doing (2) I think
 you need to revisit what you're doing! :-)

 [1] 
 http://github.com/tjcrowder/prototype/commit/79d3e1dfd32220299f0a5aceacfc6fd3ffa2a089
 [2] http://gist.github.com/182817

 Comments/suggestions/jeers welcome.  (Well, no, not jeers.)

 -- T.J.

 On Sep 8, 9:28 am, T.J. Crowder t...@crowdersoftware.com wrote:
 Hi Jim,

  Perhaps I would do:

  var B = Class.create(A, {
    nifty: function(){

      var $super = this.nifty.$super.bind( this );
      // $super refers to A.nifty() bound to this
          $super();
    }

  });

  [1] Please correct if this is wrong!

 You need to leave out the this. and use a named function instead;
 see my note to Allen for the details.  You can use #bind if you want
 to, but in my experience you're typically only making a single call to
 the superclass method, so it's not really worth the overhead.  But
 here's what it would look like:

 var B = Class.create(A, (function(){

   function nifty(){
     var $super = nifty.$super.bind( this );
     // $super refers to A.nifty() bound to this
     $super();
   }

   return {nifty: nifty};

 })());

 -- T.J.

 On Sep 8, 8:52 am, Jim Higson j...@wikizzle.org wrote:



  On Tuesday 08 September 2009 03:57:13 Allen Madsen wrote:

   TJ,
   I guess I don't understand why it wouldn't work. I'll illustrate how I
   understand it and you correct me where I'm wrong.

   var A = Class.create({
     nifty: function(){}
   });

   var B = Class.create(A, {
     nifty: function(){
       this.nifty.$super(); // refers to A.nifty()
       //this.nifty(); //would cause recursion
     }
   });

  Wouldn't you have to do this to preserve scope?

  this.nifty.$super.call( this );

  Myself, I've never liked the .call syntax much because I mistake it with
  apply: the two words seem arbitrary. But, yeah, I can see that pre-binding
  every overridden method of every object would be a big overhead.

  Perhaps I would do:

  var B = Class.create(A, {
    nifty: function(){

      var $super = this.nifty.$super.bind( this );
      // $super refers to A.nifty() bound to this
          $super();
    }

  });

  [1] Please correct if this is wrong!

  --
  Jim
  my wiki ajaxification thing:http://wikizzle.org
  my blog:http://jimhigson.blogspot.com/
 


I'm getting an error in Chrome when I click Test functionality ...

   Test loops:  (suggest about 5,000 for IE, 200,000 for Chrome,
100,000 for Firefox or Safari)
GOOD: OP(hi)
GOOD: OP(hi)  OC
GOOD: OP(hi)  OC  OGC
GOOD: NP(hi)
Exception: TypeError: Cannot call method 'call' of undefined

In FireFox ...

Test loops: (suggest about 5,000 for IE, 200,000 for Chrome, 100,000
for Firefox or Safari)
GOOD: OP(hi)
GOOD: OP(hi)  OC

[Prototype-core] Re: A more efficient $super for Prototype 2

2009-09-08 Thread T.J. Crowder

Hi,

 It really looks nicer :)

Thanks!

 I haven't run it but I guest it is possible to do

 this.method.$super.call(this, ...)

No, you need to drop the this. from the beginning of that.  See my
reply to Allen a couple up (or the PDoc comments here[1]) for why.

 arguments.callee.$supper.call(this, ...)

Yup, that works (assuming $super rather than $supper), although it's a
lot slower than using the function name.  It's still markedly faster
than the current mechanism.

-- T.J. :-)

On Sep 8, 11:20 am, Radoslav Stankov rstan...@gmail.com wrote:
 It really looks nicer :)

 I was generally using this.constructor ... and so on. But this is
 better. I haven't run it but I guest it is possible to do

 this.method.$super.call(this, ...)
 arguments.callee.$supper.call(this, ...)

 Witch is nice.
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Prototype: Core group.
To post to this group, send email to prototype-core@googlegroups.com
To unsubscribe from this group, send email to 
prototype-core-unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/prototype-core?hl=en
-~--~~~~--~~--~--~---



[Prototype-core] Re: A more efficient $super for Prototype 2

2009-09-08 Thread Richard Quadling

2009/9/8 T.J. Crowder t...@crowdersoftware.com:

 Hi,

 It really looks nicer :)

 Thanks!

 I haven't run it but I guest it is possible to do

 this.method.$super.call(this, ...)

 No, you need to drop the this. from the beginning of that.  See my
 reply to Allen a couple up (or the PDoc comments here[1]) for why.

 arguments.callee.$supper.call(this, ...)

 Yup, that works (assuming $super rather than $supper), although it's a
 lot slower than using the function name.  It's still markedly faster
 than the current mechanism.

 -- T.J. :-)

 On Sep 8, 11:20 am, Radoslav Stankov rstan...@gmail.com wrote:
 It really looks nicer :)

 I was generally using this.constructor ... and so on. But this is
 better. I haven't run it but I guest it is possible to do

 this.method.$super.call(this, ...)
 arguments.callee.$supper.call(this, ...)

 Witch is nice.
 


In the end I downloaded the archive and used src to rebuild a new prototype.

Chrome...
test loops: 50
Old mechanism time: 9666ms
New mechanism time: 639ms
*** The test was a bit short, the timing data may be suspect; try more loops.
Improvement: 93.39%, e.g., old takes 15.13 times as long as new.


A bit short Half a million loops and it's a bit short





-- 
-
Richard Quadling
Standing on the shoulders of some very clever giants!
EE : http://www.experts-exchange.com/M_248814.html
Zend Certified Engineer : http://zend.com/zce.php?c=ZEND002498r=213474731
ZOPA : http://uk.zopa.com/member/RQuadling

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Prototype: Core group.
To post to this group, send email to prototype-core@googlegroups.com
To unsubscribe from this group, send email to 
prototype-core-unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/prototype-core?hl=en
-~--~~~~--~~--~--~---



[Prototype-core] Re: A more efficient $super for Prototype 2

2009-09-08 Thread T.J. Crowder

Hi Richard,

You want to use the supercalls branch; I suspect you used master.
This should do it:

git clone git://github.com/tjcrowder/prototype.git
git checkout supercalls
rake dist

In any case, I see you got there in the end.

 A bit short Half a million loops and it's a bit short

Heh heh heh.  Yeah, well, we wouldn't want to jump to conclusions
based on insufficient test data. :-)  I have it print that out if the
total test time was less than 15 seconds.

Only a 15X improvement on Chrome, eh?  I've seen it even higher than
that...

-- T.J. :-)

On Sep 8, 11:32 am, Richard Quadling rquadl...@googlemail.com wrote:
 2009/9/8 T.J. Crowder t...@crowdersoftware.com:







  Hi,

  It really looks nicer :)

  Thanks!

  I haven't run it but I guest it is possible to do

  this.method.$super.call(this, ...)

  No, you need to drop the this. from the beginning of that.  See my
  reply to Allen a couple up (or the PDoc comments here[1]) for why.

  arguments.callee.$supper.call(this, ...)

  Yup, that works (assuming $super rather than $supper), although it's a
  lot slower than using the function name.  It's still markedly faster
  than the current mechanism.

  -- T.J. :-)

  On Sep 8, 11:20 am, Radoslav Stankov rstan...@gmail.com wrote:
  It really looks nicer :)

  I was generally using this.constructor ... and so on. But this is
  better. I haven't run it but I guest it is possible to do

  this.method.$super.call(this, ...)
  arguments.callee.$supper.call(this, ...)

  Witch is nice.

 In the end I downloaded the archive and used src to rebuild a new prototype.

 Chrome...
 test loops: 50
 Old mechanism time: 9666ms
 New mechanism time: 639ms
 *** The test was a bit short, the timing data may be suspect; try more loops.
 Improvement: 93.39%, e.g., old takes 15.13 times as long as new.

 A bit short Half a million loops and it's a bit short

 --
 -
 Richard Quadling
 Standing on the shoulders of some very clever giants!
 EE :http://www.experts-exchange.com/M_248814.html
 Zend Certified Engineer :http://zend.com/zce.php?c=ZEND002498r=213474731
 ZOPA :http://uk.zopa.com/member/RQuadling
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Prototype: Core group.
To post to this group, send email to prototype-core@googlegroups.com
To unsubscribe from this group, send email to 
prototype-core-unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/prototype-core?hl=en
-~--~~~~--~~--~--~---



[Prototype-core] Re: A more efficient $super for Prototype 2

2009-09-08 Thread T.J. Crowder

Hi all,

Just validated Radoslav's steps, and they work (provided you add the
submodules stuff), although it takes a while because you have to
retrieve everything (including submodules).  Instead, it's really easy
and very fast to just add my repo as a remote within your existing
local prototype repo, and the pull the supercalls stuff into a branch:

1. Get into your local prototype repo

2. Add mine as a remote source:

git remote add tjcrowder git://github.com/tjcrowder/prototype.git

3. Create and switch to a local supercalls branch

git branch supercalls
git checkout supercalls

4. Pull my stuff into it:

git pull tjcrowder supercalls

5. Build

rake dist

6. Profit!

Alternately, here's[1] a pre-baked copy for anyone who just wants to
grab it and play around, but of course it will go stale fairly
quickly.

[1] http://gist.github.com/182838

-- T.J.

On Sep 8, 1:15 pm, T.J. Crowder t...@crowdersoftware.com wrote:
 Hi Radoslav,

  There must be a smarter way with this, but I'm still a git newbie.

 Hey, you're better at it than I am. :-)

  Bw, this worked fine, since $super is attached to function

 It only worked because you only had a Parent  Child hierarchy. As
 soon as you throw a third level into it (the grandchild test), e.g.
 Parent  Child  GrandChild, if any of the middle layers (Child, in
 this case) tries to do a supercall, it will *endlessly recurse*.
 Really.  Again, please read my reply to Allen above[1] for details.

 [1]http://groups.google.com/group/prototype-core/browse_thread/thread/db...

 -- T.J.

 On Sep 8, 1:03 pm, Radoslav Stankov rstan...@gmail.com wrote:



  git pull origin supercalls is needed for getting not only the master
  branch. So we have:

  git clone git://github.com/tjcrowder/prototype.git
  cd prototype
  git branch supercalls
  git checkout supercalls
  git pull origin supercalls
  rake dist

  There must be a smarter way with this, but I'm still a git newbie.

  Bw, this worked fine, since $super is attached to function

  pre
  var SuperKlass = Class.create({
    update: function(){ console.log('super'); }

  });

  // written also as
  var SuperKlass = Class.create((function(){
    function update(){ console.log('super'); }
    return {update: update};

  })());

  var SubKlass = Class.create(SuperKlass, {
    update: function(){
       this.update.$super.call(this);
       console.log('sub');
    }

  });

  (new SubKlass()).update()
  /pre

  p.s. on my MacOX Leopard, it behaves very good

  Safari4:
  test loops: 10
  Old mechanism time: 686ms
  New mechanism time: 123ms

  Firefox 3.5
  test loops: 10
  Old mechanism time: 14868ms
  New mechanism time: 442ms
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Prototype: Core group.
To post to this group, send email to prototype-core@googlegroups.com
To unsubscribe from this group, send email to 
prototype-core-unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/prototype-core?hl=en
-~--~~~~--~~--~--~---



[Prototype-core] Re: A more efficient $super for Prototype 2

2009-09-08 Thread Allen Madsen
Hey TJ,
For your two suggested additions. I don't think I have ever had a use for
either. One thing I would like to suggest though is that Class.create take
an object or a function as an argument. Since it is essentially a
requirement now to use a function to create named functions that can call
super (disregarding callee), it would be nice if defining that was
simplified. So something like:

var A = Class.create({
  nifty: function(){}
});

var B = Class.create(A, function(){
  function nifty(){
nifty.$super.call(this);
  }

  return {nifty: nifty};
});

Allen Madsen
http://www.allenmadsen.com


On Tue, Sep 8, 2009 at 8:34 AM, T.J. Crowder t...@crowdersoftware.com wrote:


 Hi all,

 Just validated Radoslav's steps, and they work (provided you add the
 submodules stuff), although it takes a while because you have to
 retrieve everything (including submodules).  Instead, it's really easy
 and very fast to just add my repo as a remote within your existing
 local prototype repo, and the pull the supercalls stuff into a branch:

 1. Get into your local prototype repo

 2. Add mine as a remote source:

 git remote add tjcrowder git://github.com/tjcrowder/prototype.git

 3. Create and switch to a local supercalls branch

 git branch supercalls
 git checkout supercalls

 4. Pull my stuff into it:

 git pull tjcrowder supercalls

 5. Build

 rake dist

 6. Profit!

 Alternately, here's[1] a pre-baked copy for anyone who just wants to
 grab it and play around, but of course it will go stale fairly
 quickly.

 [1] http://gist.github.com/182838

 -- T.J.

 On Sep 8, 1:15 pm, T.J. Crowder t...@crowdersoftware.com wrote:
  Hi Radoslav,
 
   There must be a smarter way with this, but I'm still a git newbie.
 
  Hey, you're better at it than I am. :-)
 
   Bw, this worked fine, since $super is attached to function
 
  It only worked because you only had a Parent  Child hierarchy. As
  soon as you throw a third level into it (the grandchild test), e.g.
  Parent  Child  GrandChild, if any of the middle layers (Child, in
  this case) tries to do a supercall, it will *endlessly recurse*.
  Really.  Again, please read my reply to Allen above[1] for details.
 
  [1]
 http://groups.google.com/group/prototype-core/browse_thread/thread/db...
 
  -- T.J.
 
  On Sep 8, 1:03 pm, Radoslav Stankov rstan...@gmail.com wrote:
 
 
 
   git pull origin supercalls is needed for getting not only the master
   branch. So we have:
 
   git clone git://github.com/tjcrowder/prototype.git
   cd prototype
   git branch supercalls
   git checkout supercalls
   git pull origin supercalls
   rake dist
 
   There must be a smarter way with this, but I'm still a git newbie.
 
   Bw, this worked fine, since $super is attached to function
 
   pre
   var SuperKlass = Class.create({
 update: function(){ console.log('super'); }
 
   });
 
   // written also as
   var SuperKlass = Class.create((function(){
 function update(){ console.log('super'); }
 return {update: update};
 
   })());
 
   var SubKlass = Class.create(SuperKlass, {
 update: function(){
this.update.$super.call(this);
console.log('sub');
 }
 
   });
 
   (new SubKlass()).update()
   /pre
 
   p.s. on my MacOX Leopard, it behaves very good
 
   Safari4:
   test loops: 10
   Old mechanism time: 686ms
   New mechanism time: 123ms
 
   Firefox 3.5
   test loops: 10
   Old mechanism time: 14868ms
   New mechanism time: 442ms
 


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Prototype: Core group.
To post to this group, send email to prototype-core@googlegroups.com
To unsubscribe from this group, send email to 
prototype-core-unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/prototype-core?hl=en
-~--~~~~--~~--~--~---



[Prototype-core] Re: A more efficient $super for Prototype 2

2009-09-08 Thread Allen Madsen
Oh, also, you may want to throw something into update helper about your new
method of getting super.
Allen Madsen
http://www.allenmadsen.com


On Tue, Sep 8, 2009 at 9:56 AM, Allen Madsen bla...@gmail.com wrote:

 Hey TJ,
 For your two suggested additions. I don't think I have ever had a use for
 either. One thing I would like to suggest though is that Class.create take
 an object or a function as an argument. Since it is essentially a
 requirement now to use a function to create named functions that can call
 super (disregarding callee), it would be nice if defining that was
 simplified. So something like:

 var A = Class.create({
   nifty: function(){}
 });

 var B = Class.create(A, function(){
   function nifty(){
 nifty.$super.call(this);
   }

   return {nifty: nifty};
 });

 Allen Madsen
 http://www.allenmadsen.com


 On Tue, Sep 8, 2009 at 8:34 AM, T.J. Crowder t...@crowdersoftware.comwrote:


 Hi all,

 Just validated Radoslav's steps, and they work (provided you add the
 submodules stuff), although it takes a while because you have to
 retrieve everything (including submodules).  Instead, it's really easy
 and very fast to just add my repo as a remote within your existing
 local prototype repo, and the pull the supercalls stuff into a branch:

 1. Get into your local prototype repo

 2. Add mine as a remote source:

 git remote add tjcrowder git://github.com/tjcrowder/prototype.git

 3. Create and switch to a local supercalls branch

 git branch supercalls
 git checkout supercalls

 4. Pull my stuff into it:

 git pull tjcrowder supercalls

 5. Build

 rake dist

 6. Profit!

 Alternately, here's[1] a pre-baked copy for anyone who just wants to
 grab it and play around, but of course it will go stale fairly
 quickly.

 [1] http://gist.github.com/182838

 -- T.J.

 On Sep 8, 1:15 pm, T.J. Crowder t...@crowdersoftware.com wrote:
  Hi Radoslav,
 
   There must be a smarter way with this, but I'm still a git newbie.
 
  Hey, you're better at it than I am. :-)
 
   Bw, this worked fine, since $super is attached to function
 
  It only worked because you only had a Parent  Child hierarchy. As
  soon as you throw a third level into it (the grandchild test), e.g.
  Parent  Child  GrandChild, if any of the middle layers (Child, in
  this case) tries to do a supercall, it will *endlessly recurse*.
  Really.  Again, please read my reply to Allen above[1] for details.
 
  [1]
 http://groups.google.com/group/prototype-core/browse_thread/thread/db...
 
  -- T.J.
 
  On Sep 8, 1:03 pm, Radoslav Stankov rstan...@gmail.com wrote:
 
 
 
   git pull origin supercalls is needed for getting not only the master
   branch. So we have:
 
   git clone git://github.com/tjcrowder/prototype.git
   cd prototype
   git branch supercalls
   git checkout supercalls
   git pull origin supercalls
   rake dist
 
   There must be a smarter way with this, but I'm still a git newbie.
 
   Bw, this worked fine, since $super is attached to function
 
   pre
   var SuperKlass = Class.create({
 update: function(){ console.log('super'); }
 
   });
 
   // written also as
   var SuperKlass = Class.create((function(){
 function update(){ console.log('super'); }
 return {update: update};
 
   })());
 
   var SubKlass = Class.create(SuperKlass, {
 update: function(){
this.update.$super.call(this);
console.log('sub');
 }
 
   });
 
   (new SubKlass()).update()
   /pre
 
   p.s. on my MacOX Leopard, it behaves very good
 
   Safari4:
   test loops: 10
   Old mechanism time: 686ms
   New mechanism time: 123ms
 
   Firefox 3.5
   test loops: 10
   Old mechanism time: 14868ms
   New mechanism time: 442ms
 



--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Prototype: Core group.
To post to this group, send email to prototype-core@googlegroups.com
To unsubscribe from this group, send email to 
prototype-core-unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/prototype-core?hl=en
-~--~~~~--~~--~--~---



[Prototype-core] Re: A more efficient $super for Prototype 2

2009-09-08 Thread Jim Higson

On Tuesday 08 September 2009 15:27:49 Allen Madsen wrote:
 Jim,

 I like your suggestion, except that there would be no way to create private
 variables and functions that could be used in more than one function. For
 example, with my suggested method I could do:

I suppose if you wanted both you could say named functions get added to the 
class as a method, whereas the object result of executing anon functions get 
added.

Over complicated?

-- 
Jim
my wiki ajaxification thing: http://wikizzle.org
my blog: http://jimhigson.blogspot.com/

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Prototype: Core group.
To post to this group, send email to prototype-core@googlegroups.com
To unsubscribe from this group, send email to 
prototype-core-unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/prototype-core?hl=en
-~--~~~~--~~--~--~---



[Prototype-core] Re: A more efficient $super for Prototype 2

2009-09-08 Thread Robert Kieffer

I still have some serious reservations about this patch.

Before I dive into details, though, can someone please tell me why
we're not looking at Dean Edwards old Base2 approach[1], or John
Resig's variation on that[2]?  That general approach would seem to
offer a good trade-off between performance and usability.

... and it's that trade-off I have reservations about.  If Prototype
is going to replace the current $super technique, it's this tradeoff
that I would like to see a nice balance on.  And with all respect to
you, T.J., I don't think your solution has that. There's no question
it is more performant (woot!), but I have serious doubts about it's
overall usability.

The requirement for named function expressions (NFEs) puts a serious
crimp in developers coding style.  Having to declare the functions in
one section and then wrap them up in a returned data structure in
another... It's nice that this style works for Prototype, and I
appreciate the advantages, but it's not exactly commonplace (not that
anything is).  It'll definitely give more than one developer pause.
Can I politely suggest that maybe you guys are a bit too close to the
code and are taking the learning curve here for granted?

And having to explicitly type the name of each function 3-4 times to
define it will very quickly get tiresome.  It makes writing code
harder, and it makes refactoring it harder as well.  Which means more
prone to error;  there is still no IDE that is able to automatically
and accurately change the name of functions when declared like this.
With all the drum-beating around here about code maintainability, I'm
a little surprised to see this issue treated so lightly.

Most importantly, the syntax for invoking a supermethod, while not
quite as horrid as some others we've seen and discussed, is still not
that great.  I mean, come on, close your eyes, take a few deep
breaths, and then look at it...

nifty.$super.call(this, spiffy)

... .vs. the current style:

$super(spiffy)

... or what the Dean Edwards/John Resig style:

this._super(spiffy)

I know, I know, the current style has performance issues.  But for a
lot of developers a simpler, less confusing syntax will trump that.  I
suspect most will continue to use the old $super scheme, which will
make it much harder to deprecate than you might expect.  And if the
old $super scheme is gonna stick around for a while because the new
scheme ain't good enough, than at the end of the day this new code
is just unnecessary code bloat.  Certainly Prototype itself doesn't
need it - the Ajax.* classes and Timed Observer aren't used in
situations where $super is called so often that the incremental
performance improvement will make a difference.

Sorry, I probably should have posted this before you spent your time
implementing your patch.  Still... I hope this is a constructive gut
check for folks.

- rwk

[1] http://dean.edwards.name/weblog/2006/03/base/
[2] http://ejohn.org/blog/simple-javascript-inheritance/
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Prototype: Core group.
To post to this group, send email to prototype-core@googlegroups.com
To unsubscribe from this group, send email to 
prototype-core-unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/prototype-core?hl=en
-~--~~~~--~~--~--~---



[Prototype-core] Re: A more efficient $super for Prototype 2

2009-09-08 Thread T.J. Crowder

@Allen,

 For your two suggested additions. I don't think I have ever had a use for
 either.

Thanks.

 One thing I would like to suggest though is that Class.create
 take an object or a function as an argument.

I _really_ like that idea, not least because it seems to me that by
reducing the *seeming* complexity it makes it much easier for relative
novices to adopt using named functions.  But unfortunately it would a
further API change, because otherwise Class.create can't tell whether
the first argument is a  base class constructor or a function you want
it to call to retrieve the members object:

var X = Class.create(BaseClass);
var Y = Class.create(function() {
function nifty() { ... }
return {nifty: nifty};
});

You see the problem.  The API change wouldn't need to be large, it's
just suddenly we're impacting the API more than we otherwise have to,
and my gut reaction to that is usually caution (not least because
unless I caution myself, I get a bit change-happy).

None of which is meant to say A) That I'd be opposed to it if a bunch
of smart people said it was worth it (quite the opposite, in fact); or
B) That I'm not going to *immediately* steal your idea for my own
projects. :-)

FWIW, and there are 18 ways to skin this cat, but if we did anything
I'd prefer to leave Class.create alone, but I'd be really interested
in the idea of providing a new entry point (Class.define, perhaps)
that provides this new functionality and which solves the problem of
how to specify the base class in some clever way.  Perhaps a new
thread for this sub-topic?

@Jim,

 Ie, Class.create takes any number of objects of functions or functions. If
 functions, the function name is used.

I see where you're coming from, but FWIW I'm with Allen on this one.
Also, there's no standard way to get the name of a function until
ECMAScript5 (which standardizes the truly outrageous idea that
function instances should have -- gasp! -- a name property), and at
the moment although Firefox 3.5, Chrome 2, and Safari 4 all already
have that property, IE7 (at least, haven't tested IE8) and Opera10 do
not.

-- T.J. :-)

On Sep 8, 3:27 pm, Allen Madsen bla...@gmail.com wrote:
 Jim,
 I like your suggestion, except that there would be no way to create private
 variables and functions that could be used in more than one function. For
 example, with my suggested method I could do:

 Var A = Class.create(function(){
   var privateVar = 0;

   function privateFunction(){}

   function nifty(){
     privateFunction();
     privateVar = 3;
   }

   return {nifty: nifty};

 });

 I'd much rather see it in this form.

 Allen Madsenhttp://www.allenmadsen.com



 On Tue, Sep 8, 2009 at 10:12 AM, Jim Higson j...@wikizzle.org wrote:

  On Tuesday 08 September 2009 14:56:06 Allen Madsen wrote:
   Hey TJ,
   For your two suggested additions. I don't think I have ever had a use for
   either. One thing I would like to suggest though is that Class.create
  take
   an object or a function as an argument. Since it is essentially a
   requirement now to use a function to create named functions that can call
   super (disregarding callee), it would be nice if defining that was
   simplified. So something like:

   var A = Class.create({
     nifty: function(){}
   });

   var B = Class.create(A, function(){
     function nifty(){
       nifty.$super.call(this);
     }

     return {nifty: nifty};
   });

  How about simplifying further:

  var B = Class.create( A,
      function nifty(){
         nifty.$super.call(this);
     }

  ,   function alsoNifty(){
         this.nifty();
     }
  );

  Ie, Class.create takes any number of objects of functions or functions. If
  functions, the function name is used.

  --
  Jim
  my wiki ajaxification thing:http://wikizzle.org
  my blog:http://jimhigson.blogspot.com/
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Prototype: Core group.
To post to this group, send email to prototype-core@googlegroups.com
To unsubscribe from this group, send email to 
prototype-core-unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/prototype-core?hl=en
-~--~~~~--~~--~--~---



[Prototype-core] Re: A more efficient $super for Prototype 2

2009-09-08 Thread Jim Higson

On Tuesday 08 September 2009 14:56:06 Allen Madsen wrote:
 Hey TJ,
 For your two suggested additions. I don't think I have ever had a use for
 either. One thing I would like to suggest though is that Class.create take
 an object or a function as an argument. Since it is essentially a
 requirement now to use a function to create named functions that can call
 super (disregarding callee), it would be nice if defining that was
 simplified. So something like:

 var A = Class.create({
   nifty: function(){}
 });

 var B = Class.create(A, function(){
   function nifty(){
 nifty.$super.call(this);
   }

   return {nifty: nifty};
 });

How about simplifying further:

var B = Class.create( A,
function nifty(){
nifty.$super.call(this);
}

,   function alsoNifty(){
this.nifty();
}
);

Ie, Class.create takes any number of objects of functions or functions. If 
functions, the function name is used.

-- 
Jim
my wiki ajaxification thing: http://wikizzle.org
my blog: http://jimhigson.blogspot.com/

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Prototype: Core group.
To post to this group, send email to prototype-core@googlegroups.com
To unsubscribe from this group, send email to 
prototype-core-unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/prototype-core?hl=en
-~--~~~~--~~--~--~---



[Prototype-core] Re: A more efficient $super for Prototype 2

2009-09-08 Thread Allen Madsen

@TJ
I don't think it would be hard to tell the difference between a base
class construct and a function. You would just need some extra work in
construction of the base class. After the construction of klass, you
could set a property so that it is identifiable. For example:

function klass() {
  this.initialize.apply(this, arguments);
}
if( !klass.name ) klass.name = 'klass';

Then you could do:

if(Object.isFunction(value)){
  if(value.name === 'klass'){
//Do base class stuff
  } else {
//Do function generator
  }
}

I hope its clear where these snippets relate to the source.

Allen Madsen
http://www.allenmadsen.com


On Tue, Sep 8, 2009 at 11:18 AM, T.J. Crowder t...@crowdersoftware.com wrote:

 @Allen,

  For your two suggested additions. I don't think I have ever had a use for
  either.

 Thanks.

  One thing I would like to suggest though is that Class.create
  take an object or a function as an argument.

 I _really_ like that idea, not least because it seems to me that by
 reducing the *seeming* complexity it makes it much easier for relative
 novices to adopt using named functions.  But unfortunately it would a
 further API change, because otherwise Class.create can't tell whether
 the first argument is a  base class constructor or a function you want
 it to call to retrieve the members object:

    var X = Class.create(BaseClass);
    var Y = Class.create(function() {
        function nifty() { ... }
        return {nifty: nifty};
    });

 You see the problem.  The API change wouldn't need to be large, it's
 just suddenly we're impacting the API more than we otherwise have to,
 and my gut reaction to that is usually caution (not least because
 unless I caution myself, I get a bit change-happy).

 None of which is meant to say A) That I'd be opposed to it if a bunch
 of smart people said it was worth it (quite the opposite, in fact); or
 B) That I'm not going to *immediately* steal your idea for my own
 projects. :-)

 FWIW, and there are 18 ways to skin this cat, but if we did anything
 I'd prefer to leave Class.create alone, but I'd be really interested
 in the idea of providing a new entry point (Class.define, perhaps)
 that provides this new functionality and which solves the problem of
 how to specify the base class in some clever way.  Perhaps a new
 thread for this sub-topic?

 @Jim,

  Ie, Class.create takes any number of objects of functions or functions. If
  functions, the function name is used.

 I see where you're coming from, but FWIW I'm with Allen on this one.
 Also, there's no standard way to get the name of a function until
 ECMAScript5 (which standardizes the truly outrageous idea that
 function instances should have -- gasp! -- a name property), and at
 the moment although Firefox 3.5, Chrome 2, and Safari 4 all already
 have that property, IE7 (at least, haven't tested IE8) and Opera10 do
 not.

 -- T.J. :-)

 On Sep 8, 3:27 pm, Allen Madsen bla...@gmail.com wrote:
  Jim,
  I like your suggestion, except that there would be no way to create private
  variables and functions that could be used in more than one function. For
  example, with my suggested method I could do:
 
  Var A = Class.create(function(){
    var privateVar = 0;
 
    function privateFunction(){}
 
    function nifty(){
      privateFunction();
      privateVar = 3;
    }
 
    return {nifty: nifty};
 
  });
 
  I'd much rather see it in this form.
 
  Allen Madsenhttp://www.allenmadsen.com
 
 
 
  On Tue, Sep 8, 2009 at 10:12 AM, Jim Higson j...@wikizzle.org wrote:
 
   On Tuesday 08 September 2009 14:56:06 Allen Madsen wrote:
Hey TJ,
For your two suggested additions. I don't think I have ever had a use 
for
either. One thing I would like to suggest though is that Class.create
   take
an object or a function as an argument. Since it is essentially a
requirement now to use a function to create named functions that can 
call
super (disregarding callee), it would be nice if defining that was
simplified. So something like:
 
var A = Class.create({
  nifty: function(){}
});
 
var B = Class.create(A, function(){
  function nifty(){
    nifty.$super.call(this);
  }
 
  return {nifty: nifty};
});
 
   How about simplifying further:
 
   var B = Class.create( A,
       function nifty(){
          nifty.$super.call(this);
      }
 
   ,   function alsoNifty(){
          this.nifty();
      }
   );
 
   Ie, Class.create takes any number of objects of functions or functions. If
   functions, the function name is used.
 
   --
   Jim
   my wiki ajaxification thing:http://wikizzle.org
   my blog:http://jimhigson.blogspot.com/
 

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Prototype: Core group.
To post to this group, send email to prototype-core@googlegroups.com
To unsubscribe from this group, send email to 
prototype-core-unsubscr...@googlegroups.com

[Prototype-core] Re: A more efficient $super for Prototype 2

2009-09-08 Thread T.J. Crowder

Hi Allen,

 After the construction of klass, you
 could set a property so that it is identifiable.

Doh!  Of course, since we only allow deriving from classes created via
Class.create.  I wouldn't go with name, though, since the
ECMAScript5 spec actually defines name for functions.  But
_createdByPrototype would work (and echos the _extendedByPrototype
property on extended Elements)...

Gets my vote, as you say, makes the syntax much more like several
other things we do:

var Thingy = Class.create(function(){
// Define
function nifty() { ... }
function spiffy() { ... }
function keen() { ... }

// Export public methods
return {nifty: nifty, spiffy: spiffy, keen: keen};
});

...while still accepting the form where we've already been given an
object.

Nice one!
--
T.J. Crowder
tj / crowder software / com
www.crowdersoftware.com


On Sep 8, 5:00 pm, Allen Madsen bla...@gmail.com wrote:
 @TJ
 I don't think it would be hard to tell the difference between a base
 class construct and a function. You would just need some extra work in
 construction of the base class. After the construction of klass, you
 could set a property so that it is identifiable. For example:

 function klass() {
   this.initialize.apply(this, arguments);}

 if( !klass.name ) klass.name = 'klass';

 Then you could do:

 if(Object.isFunction(value)){
   if(value.name === 'klass'){
     //Do base class stuff
   } else {
     //Do function generator
   }

 }

 I hope its clear where these snippets relate to the source.

 Allen Madsenhttp://www.allenmadsen.com



 On Tue, Sep 8, 2009 at 11:18 AM, T.J. Crowder t...@crowdersoftware.com 
 wrote:

  @Allen,

   For your two suggested additions. I don't think I have ever had a use for
   either.

  Thanks.

   One thing I would like to suggest though is that Class.create
   take an object or a function as an argument.

  I _really_ like that idea, not least because it seems to me that by
  reducing the *seeming* complexity it makes it much easier for relative
  novices to adopt using named functions.  But unfortunately it would a
  further API change, because otherwise Class.create can't tell whether
  the first argument is a  base class constructor or a function you want
  it to call to retrieve the members object:

     var X = Class.create(BaseClass);
     var Y = Class.create(function() {
         function nifty() { ... }
         return {nifty: nifty};
     });

  You see the problem.  The API change wouldn't need to be large, it's
  just suddenly we're impacting the API more than we otherwise have to,
  and my gut reaction to that is usually caution (not least because
  unless I caution myself, I get a bit change-happy).

  None of which is meant to say A) That I'd be opposed to it if a bunch
  of smart people said it was worth it (quite the opposite, in fact); or
  B) That I'm not going to *immediately* steal your idea for my own
  projects. :-)

  FWIW, and there are 18 ways to skin this cat, but if we did anything
  I'd prefer to leave Class.create alone, but I'd be really interested
  in the idea of providing a new entry point (Class.define, perhaps)
  that provides this new functionality and which solves the problem of
  how to specify the base class in some clever way.  Perhaps a new
  thread for this sub-topic?

  @Jim,

   Ie, Class.create takes any number of objects of functions or functions. If
   functions, the function name is used.

  I see where you're coming from, but FWIW I'm with Allen on this one.
  Also, there's no standard way to get the name of a function until
  ECMAScript5 (which standardizes the truly outrageous idea that
  function instances should have -- gasp! -- a name property), and at
  the moment although Firefox 3.5, Chrome 2, and Safari 4 all already
  have that property, IE7 (at least, haven't tested IE8) and Opera10 do
  not.

  -- T.J. :-)

  On Sep 8, 3:27 pm, Allen Madsen bla...@gmail.com wrote:
   Jim,
   I like your suggestion, except that there would be no way to create 
   private
   variables and functions that could be used in more than one function. For
   example, with my suggested method I could do:

   Var A = Class.create(function(){
     var privateVar = 0;

     function privateFunction(){}

     function nifty(){
       privateFunction();
       privateVar = 3;
     }

     return {nifty: nifty};

   });

   I'd much rather see it in this form.

   Allen Madsenhttp://www.allenmadsen.com

   On Tue, Sep 8, 2009 at 10:12 AM, Jim Higson j...@wikizzle.org wrote:

On Tuesday 08 September 2009 14:56:06 Allen Madsen wrote:
 Hey TJ,
 For your two suggested additions. I don't think I have ever had a use 
 for
 either. One thing I would like to suggest though is that Class.create
take
 an object or a function as an argument. Since it is essentially a
 requirement now to use a function to create named functions that can 
 call
 super (disregarding 

[Prototype-core] Re: A more efficient $super for Prototype 2

2009-09-08 Thread T.J. Crowder

Hi Robert,

Thanks for your thoughts on this.

 The requirement for named function expressions (NFEs) puts a serious
 crimp in developers coding style.

This mechanism does _not_ require NFEs.  You can use anonymous
functions and call the super via arguments.callee if you like, and
still get big performance improvement (and stop relying on function
decompilation, although you lose ECMA5 strict mode compliance).  The
invocation syntax if you use anonymous functions is ugly enough:

var Thingy = Class.create({

nifty: function(arg) {

arguments.callee.$super.call(this, arg);
}
});

...that I would (in fact, did) suggest a helper:

var Thingy = Class.create({

nifty: function(arg) {

this.callSuper(arguments, arg);
}
});

 Before I dive into details, though, can someone please tell me why
 we're not looking at Dean Edwards old Base2 approach[1], or John
 Resig's variation on that[2]?

We should definitely consider various options.  This started because I
sort of accidentally went down a road, found what I thought was a
really nifty solution, and posted asking whether others were
interested in it.

My issue with Resig's approach would be the number of introduced
closures and the slippery _super method, which has too much magic in
it for my taste. These things are subjective.  It also won't perform
as well, but we're talking a small increment, and as you say trade-
offs come into play.

 I mean, come on, close your eyes, take a few deep
 breaths, and then look at it...

 nifty.$super.call(this, spiffy)

There are lots of constructs that look a bit alien at first.  To me
this isn't one of them (and I'm no JavaScript master) but I totally
recognise that for some novices there's going to be a certain amount
of just do it like this, eventually you'll understand why.  That's
true of lots of things.  A novice who doesn't know about Function#call
needs to be taught about Function#call, in my view.

If we provide a helper, it could accept either 'arguments' (for
anonymous functions) or the function instance (for named fucntions),
so this:

nifty.$super.call(this, spiffy);

...could be:

this.callSuper(nifty, spiffy);

...if we think that's more helpful.  The cost is an extra function
call, which compared with the various other savings we're making isn't
a big deal.

Thanks again for jumping into this,
--
T.J. Crowder
tj / crowder software / com
www.crowdersoftware.com


On Sep 8, 4:11 pm, Robert Kieffer bro...@gmail.com wrote:
 I still have some serious reservations about this patch.

 Before I dive into details, though, can someone please tell me why
 we're not looking at Dean Edwards old Base2 approach[1], or John
 Resig's variation on that[2]?  That general approach would seem to
 offer a good trade-off between performance and usability.

 ... and it's that trade-off I have reservations about.  If Prototype
 is going to replace the current $super technique, it's this tradeoff
 that I would like to see a nice balance on.  And with all respect to
 you, T.J., I don't think your solution has that. There's no question
 it is more performant (woot!), but I have serious doubts about it's
 overall usability.

 The requirement for named function expressions (NFEs) puts a serious
 crimp in developers coding style.  Having to declare the functions in
 one section and then wrap them up in a returned data structure in
 another... It's nice that this style works for Prototype, and I
 appreciate the advantages, but it's not exactly commonplace (not that
 anything is).  It'll definitely give more than one developer pause.
 Can I politely suggest that maybe you guys are a bit too close to the
 code and are taking the learning curve here for granted?

 And having to explicitly type the name of each function 3-4 times to
 define it will very quickly get tiresome.  It makes writing code
 harder, and it makes refactoring it harder as well.  Which means more
 prone to error;  there is still no IDE that is able to automatically
 and accurately change the name of functions when declared like this.
 With all the drum-beating around here about code maintainability, I'm
 a little surprised to see this issue treated so lightly.

 Most importantly, the syntax for invoking a supermethod, while not
 quite as horrid as some others we've seen and discussed, is still not
 that great.  I mean, come on, close your eyes, take a few deep
 breaths, and then look at it...

     nifty.$super.call(this, spiffy)

 ... .vs. the current style:

     $super(spiffy)

 ... or what the Dean Edwards/John Resig style:

     this._super(spiffy)

 I know, I know, the current style has performance issues.  But for a
 lot of developers a simpler, less confusing syntax will trump that.  I
 suspect most will continue to use the old $super scheme, which will
 make it much harder to deprecate than you might expect.  And if the
 old $super scheme is gonna stick around for a while because 

[Prototype-core] Re: A more efficient $super for Prototype 2

2009-09-08 Thread Allen Madsen
Jim,
I like your suggestion, except that there would be no way to create private
variables and functions that could be used in more than one function. For
example, with my suggested method I could do:

Var A = Class.create(function(){
  var privateVar = 0;

  function privateFunction(){}

  function nifty(){
privateFunction();
privateVar = 3;
  }

  return {nifty: nifty};
});

I'd much rather see it in this form.

Allen Madsen
http://www.allenmadsen.com


On Tue, Sep 8, 2009 at 10:12 AM, Jim Higson j...@wikizzle.org wrote:


 On Tuesday 08 September 2009 14:56:06 Allen Madsen wrote:
  Hey TJ,
  For your two suggested additions. I don't think I have ever had a use for
  either. One thing I would like to suggest though is that Class.create
 take
  an object or a function as an argument. Since it is essentially a
  requirement now to use a function to create named functions that can call
  super (disregarding callee), it would be nice if defining that was
  simplified. So something like:
 
  var A = Class.create({
nifty: function(){}
  });
 
  var B = Class.create(A, function(){
function nifty(){
  nifty.$super.call(this);
}
 
return {nifty: nifty};
  });

 How about simplifying further:

 var B = Class.create( A,
 function nifty(){
nifty.$super.call(this);
}

 ,   function alsoNifty(){
this.nifty();
}
 );

 Ie, Class.create takes any number of objects of functions or functions. If
 functions, the function name is used.

 --
 Jim
 my wiki ajaxification thing: http://wikizzle.org
 my blog: http://jimhigson.blogspot.com/

 


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Prototype: Core group.
To post to this group, send email to prototype-core@googlegroups.com
To unsubscribe from this group, send email to 
prototype-core-unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/prototype-core?hl=en
-~--~~~~--~~--~--~---



[Prototype-core] Re: A more efficient $super for Prototype 2

2009-09-08 Thread Robert Kieffer

On Sep 8, 8:44 am, T.J. Crowder t...@crowdersoftware.com wrote:
             arguments.callee.$super.call(this, arg);
             this.callSuper(arguments, arg);

six of one, half-dozen of the other... but I suppose there is no
perfect solution.  Still, it's hard to swallow something this
convoluted when you've gotten used to $super (or this._super() ) :-P

 My issue with Resig's approach would be the number of introduced
 closures and the slippery _super method, which has too much magic in
 it for my taste. These things are subjective.  It also won't perform
 as well, but we're talking a small increment, and as you say trade-
 offs come into play.

I have to confess it's been long enough since I looked at that code
that I don't have an opinion about it.  I do know that it performance
tested well, and I definitely prefer the invocation syntax.

Honestly, at this point I'm mostly worried that that we may get
enamored with a solution that is different, but not necessarily all
that much better.  More performant, yes, but at the cost of
usability.  I'm tempted, even, to argue for the removal of supermethod
invocation altogether in Prototype.  It's not like it actually needs
it - there are a couple places where $super is used, but it would be
trivial to rewrite that to where it's not necessary.  Developers would
benefit from a smaller Prototype codebase, and they code pick and
choose the supermethod technique that best met their needs, and import
the appropriate script for that.

That notion is both heretical and ironic I suppose, since I guess I
started the whole look how shitty Prototype supermethod performance
is! thread.  But history has taught me that developers who write code
without having a concrete use for it very rarely make the right
choices.  It's much better to let requirements drive the code choices,
rather than the other way around.

Okay, climbing down off my soapbox now to go get lunch. :-)

- rwk
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Prototype: Core group.
To post to this group, send email to prototype-core@googlegroups.com
To unsubscribe from this group, send email to 
prototype-core-unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/prototype-core?hl=en
-~--~~~~--~~--~--~---



[Prototype-core] Re: A more efficient $super for Prototype 2

2009-09-08 Thread T.J. Crowder

Hi Robert,

  arguments.callee.$super.call(this, arg);
  this.callSuper(arguments, arg);

 six of one, half-dozen of the other...

Um, this.callSuper(arguments, arg) (or this.callSuper(nifty, arg))
is precisely *one* argument more than Resig's this._super(arg), but
without the cost of the closures and unnecessary, misleading (IMV)
magic.  It's a lot clearer than the raw syntax needed with anonymous
functions.  Six of one, half-dozen of the other seems a bit harsh.

 Honestly, at this point I'm mostly worried that that we may get
 enamored with a solution that is different, but not necessarily all
 that much better.  More performant, yes, but at the cost of
 usability...

That's interesting.  I started down this road precisely because I
found the existing API flawed; the performance and compliance aspects
came later.  I'm not at all interested in replacing things without a
compelling reason, we all have better things to do.

 I'm tempted, even, to argue for the removal of supermethod
 invocation altogether in Prototype.

FWIW, I think that would be a mistake (but then, I use supercalls and
had a concrete reason for going down this path).  Not only because
it's a useful feature, but also because it's one of the things people
of a certain background look for in a JavaScript library.

I didn't realize you'd done a crappy performance in supercalls
thrread (I was away from this group for a while).  I'd seen the
excellent work you did with curried and bound functions, though, and
I'm glad to hear that will be finding its way into 1.6.1.

-- T.J. :-)

On Sep 8, 7:43 pm, Robert Kieffer bro...@gmail.com wrote:
 On Sep 8, 8:44 am, T.J. Crowder t...@crowdersoftware.com wrote:

              arguments.callee.$super.call(this, arg);
              this.callSuper(arguments, arg);

 six of one, half-dozen of the other... but I suppose there is no
 perfect solution.  Still, it's hard to swallow something this
 convoluted when you've gotten used to $super (or this._super() ) :-P

  My issue with Resig's approach would be the number of introduced
  closures and the slippery _super method, which has too much magic in
  it for my taste. These things are subjective.  It also won't perform
  as well, but we're talking a small increment, and as you say trade-
  offs come into play.

 I have to confess it's been long enough since I looked at that code
 that I don't have an opinion about it.  I do know that it performance
 tested well, and I definitely prefer the invocation syntax.

 Honestly, at this point I'm mostly worried that that we may get
 enamored with a solution that is different, but not necessarily all
 that much better.  More performant, yes, but at the cost of
 usability.  I'm tempted, even, to argue for the removal of supermethod
 invocation altogether in Prototype.  It's not like it actually needs
 it - there are a couple places where $super is used, but it would be
 trivial to rewrite that to where it's not necessary.  Developers would
 benefit from a smaller Prototype codebase, and they code pick and
 choose the supermethod technique that best met their needs, and import
 the appropriate script for that.

 That notion is both heretical and ironic I suppose, since I guess I
 started the whole look how shitty Prototype supermethod performance
 is! thread.  But history has taught me that developers who write code
 without having a concrete use for it very rarely make the right
 choices.  It's much better to let requirements drive the code choices,
 rather than the other way around.

 Okay, climbing down off my soapbox now to go get lunch. :-)

 - rwk
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Prototype: Core group.
To post to this group, send email to prototype-core@googlegroups.com
To unsubscribe from this group, send email to 
prototype-core-unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/prototype-core?hl=en
-~--~~~~--~~--~--~---



[Prototype-core] Re: A more efficient $super for Prototype 2

2009-09-08 Thread Tobie Langel

Allen, You can do this already pretty easily.

Just do:

Var A = Class.create(function(){
  var privateVar = 0;
  function privateFunction(){}
  function nifty(){
privateFunction();
privateVar = 3;
  }
  return {nifty: nifty};
}());

Just note that in both cases, those private variables are `class`
variables
 shared between all instances.
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Prototype: Core group.
To post to this group, send email to prototype-core@googlegroups.com
To unsubscribe from this group, send email to 
prototype-core-unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/prototype-core?hl=en
-~--~~~~--~~--~--~---



[Prototype-core] Re: A more efficient $super for Prototype 2

2009-09-08 Thread kangax



On Sep 8, 11:11 am, Robert Kieffer bro...@gmail.com wrote:
 I still have some serious reservations about this patch.

 Before I dive into details, though, can someone please tell me why
 we're not looking at Dean Edwards old Base2 approach[1], or John
 Resig's variation on that[2]?  That general approach would seem to
 offer a good trade-off between performance and usability.

Last time I checked, Resig's implementation relied on function
decompilation too, which we are trying to avoid this time.


 ... and it's that trade-off I have reservations about.  If Prototype
 is going to replace the current $super technique, it's this tradeoff
 that I would like to see a nice balance on.  And with all respect to
 you, T.J., I don't think your solution has that. There's no question
 it is more performant (woot!), but I have serious doubts about it's
 overall usability.

 The requirement for named function expressions (NFEs) puts a serious
 crimp in developers coding style.  Having to declare the functions in

Actually, there's no such requirement. You are free to use anonymous
function expressions, named function expressions or function
declarations. You only need to have a reference to a function; doesn't
matter how you created it and which identifier you gave to it.

var f;
Class.create({
  initialize: (f = function(){
// ...
  })
});

There's your `f`, referencing function in question. No Identifier
needed.

 one section and then wrap them up in a returned data structure in
 another... It's nice that this style works for Prototype, and I
 appreciate the advantages, but it's not exactly commonplace (not that
 anything is).  It'll definitely give more than one developer pause.
 Can I politely suggest that maybe you guys are a bit too close to the
 code and are taking the learning curve here for granted?

 And having to explicitly type the name of each function 3-4 times to
 define it will very quickly get tiresome.  It makes writing code
 harder, and it makes refactoring it harder as well.  Which means more

I agree. Repetition of function names is by far the biggest downside
to this approach. And, of course, it is impossible to not repeat
function name without either relying on function decompilation or
completely hog performance by blindly wrapping every single method
with a closure to its parent.

[...]

--
kangax
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Prototype: Core group.
To post to this group, send email to prototype-core@googlegroups.com
To unsubscribe from this group, send email to 
prototype-core-unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/prototype-core?hl=en
-~--~~~~--~~--~--~---



[Prototype-core] Re: A more efficient $super for Prototype 2

2009-09-08 Thread Tobie Langel


 T.J., could you point me to the exact section specifying `name` on
 Function objects? I don't remember seeing it in ES5.

That's because it's not part of that spec. If I remember correctly it
was discussed for Harmony.

Best,

Tobie
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Prototype: Core group.
To post to this group, send email to prototype-core@googlegroups.com
To unsubscribe from this group, send email to 
prototype-core-unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/prototype-core?hl=en
-~--~~~~--~~--~--~---



[Prototype-core] Re: A more efficient $super for Prototype 2

2009-09-08 Thread Robert Kieffer
On Tue, Sep 8, 2009 at 1:21 PM, T.J. Crowder t...@crowdersoftware.com wrote:


 Hi Robert,

   arguments.callee.$super.call(this, arg);
   this.callSuper(arguments, arg);
 
  six of one, half-dozen of the other...

 Um, this.callSuper(arguments, arg) (or this.callSuper(nifty, arg))
 is precisely *one* argument more than Resig's this._super(arg), but
 without the cost of the closures and unnecessary, misleading (IMV)
 magic.  It's a lot clearer than the raw syntax needed with anonymous
 functions.  Six of one, half-dozen of the other seems a bit harsh.


I apologize, I was being glib (hence the quotes.)  But there is a grain of
truth there.  Both these incantations are unintuitive in their own way.

callSuper may have only one more argument but it's a wierd one for sure.
Especially for developers unfamiliar with 'arguments' and its 'callee'
property.  Many devs will treat this as yet another piece of JS voodoo code
they have to remember - you do it just because.  And what if the super
method takes different arguments than the sub method, Wait a minute, why am
I passing an array with 'foo'  'bar' in it, when I only want to hand 'baz'
to the supermethod?

 Honestly, at this point I'm mostly worried that that we may get
  enamored with a solution that is different, but not necessarily all
  that much better.  More performant, yes, but at the cost of
  usability...

 That's interesting.  I started down this road precisely because I
 found the existing API flawed;


Was it the API you found flawed, or the implementation of that API?  I think
the $super argument is a rather elegant solution.  Non-standard, sure, and
lacking performance, but conceptually elegant.  In essence: If you need to
access $super, just pass it to yourself as the first argument.  It's easy
to remember, and hard to screw up.

I didn't realize you'd done a crappy performance in supercalls
 thrread (I was away from this group for a while).  I'd seen the
 excellent work you did with curried and bound functions, though, and
 I'm glad to hear that will be finding its way into 1.6.1.


It wasn't a thread in this group but, rather, the blog post I did a while
back that got some attention on Ajaxian.com and that other folks ran with
for a bit on their own blogs:

http://ajaxian.com/archives/javascript-inheritance-performance

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Prototype: Core group.
To post to this group, send email to prototype-core@googlegroups.com
To unsubscribe from this group, send email to 
prototype-core-unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/prototype-core?hl=en
-~--~~~~--~~--~--~---



[Prototype-core] Re: A more efficient $super for Prototype 2

2009-09-07 Thread Rick Waldron
TJ...

I once woke up from a nap in the middle of a saturday and solved a silly
issue i was having with event bubbling/propagation... I had seen the
solution in code as the last thing before I woke up. I tried it... and it
worked. The point: never feel bad about waking up to code on the brain :)

Rick

On Sun, Sep 6, 2009 at 5:38 AM, T.J. Crowder t...@crowdersoftware.com wrote:


   I think you need this.nifty.$super.call(this, foo);
 
  You don't, although that also works.

 Ack!  Sorry, too early in the morning, hadn't had enough coffee.

 That does *not* work, because you always refer to the bottommost
 subclass's nifty (this.nifty is always the bottommost function), so
 you end up endlessly recursing.  Wow that's an easy trap to fall into.

 No, it's either use the function's name unadorned, or use
 arguments.callee and pay the performance penalty.  Personally, I
 prefer using the function's name. :-)

 -- T.J. :-)

 On Sep 6, 8:48 am, T.J. Crowder t...@crowdersoftware.com wrote:
  Hi Allen,
 
   I think you need this.nifty.$super.call(this, foo);
 
  You don't, although that also works.  A named function's name is in
  scope within the function:
 
  function foo(bar) {
  alert(typeof foo); // Alerts function
  }
 
  However, I was thinking about anonymous functions this morning while
  waking up (pathetic, isn't it?) and realized that even if you don't
  use a named function, you can avoid arguments.callee with exactly the
  form you describe:  this.nifty.$super.call(this, foo);  I don't like
  the repetition of this, but if you don't have time to switch
  everything over to named functions (I'm thinking of retrofitting
  efforts), it's a reasonable first step, and I assume (haven't tested
  it yet) still gets speed gains over arguments.callee.
 
  Will be posting a sample implementation (it's wonderfully simple, but
  there are a couple of edge cases around dynamic updates of classes)
  and tests ASAP, but I want to get some of the Prototype documentation
  issues sorted out first (transferring the old doc to the new format
  and updating), since that's more urgent.
 
  -- T.J. :-)
 
  On Sep 5, 2:46 pm, Allen Madsen bla...@gmail.com wrote:
 
 
 
 var Thingy = Class.create({
 nifty: function nifty(foo, bar) {
 nifty.$super.call(this, foo);
 }
 });
 
 It just ignores the function name and complains that 'nifty' is not
 defined.  This works:
 
   I think you need this.nifty.$super.call(this, foo);
 
   Allen Madsenhttp://www.allenmadsen.com
 


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Prototype: Core group.
To post to this group, send email to prototype-core@googlegroups.com
To unsubscribe from this group, send email to 
prototype-core-unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/prototype-core?hl=en
-~--~~~~--~~--~--~---



[Prototype-core] Re: A more efficient $super for Prototype 2

2009-09-07 Thread Allen Madsen
TJ,
I guess I don't understand why it wouldn't work. I'll illustrate how I
understand it and you correct me where I'm wrong.

var A = Class.create({
  nifty: function(){}
});

var B = Class.create(A, {
  nifty: function(){
this.nifty.$super(); // refers to A.nifty()
//this.nifty(); //would cause recursion
  }
});

Also, if what I'm thinking is correct, there are some interesting side
effects that weren't possible before. Such as:

var C = Class.create(B, {
  nifty: function(){
this.nifty.$super.$super(); //refers to A.nifty() instead of B.nifty()
  },
  crappy: function(){
this.nifty.$super(); //calls super of another function
  }
});

Allen Madsen
http://www.allenmadsen.com


On Sun, Sep 6, 2009 at 5:38 AM, T.J. Crowder t...@crowdersoftware.com wrote:


   I think you need this.nifty.$super.call(this, foo);
 
  You don't, although that also works.

 Ack!  Sorry, too early in the morning, hadn't had enough coffee.

 That does *not* work, because you always refer to the bottommost
 subclass's nifty (this.nifty is always the bottommost function), so
 you end up endlessly recursing.  Wow that's an easy trap to fall into.

 No, it's either use the function's name unadorned, or use
 arguments.callee and pay the performance penalty.  Personally, I
 prefer using the function's name. :-)

 -- T.J. :-)

 On Sep 6, 8:48 am, T.J. Crowder t...@crowdersoftware.com wrote:
  Hi Allen,
 
   I think you need this.nifty.$super.call(this, foo);
 
  You don't, although that also works.  A named function's name is in
  scope within the function:
 
  function foo(bar) {
  alert(typeof foo); // Alerts function
  }
 
  However, I was thinking about anonymous functions this morning while
  waking up (pathetic, isn't it?) and realized that even if you don't
  use a named function, you can avoid arguments.callee with exactly the
  form you describe:  this.nifty.$super.call(this, foo);  I don't like
  the repetition of this, but if you don't have time to switch
  everything over to named functions (I'm thinking of retrofitting
  efforts), it's a reasonable first step, and I assume (haven't tested
  it yet) still gets speed gains over arguments.callee.
 
  Will be posting a sample implementation (it's wonderfully simple, but
  there are a couple of edge cases around dynamic updates of classes)
  and tests ASAP, but I want to get some of the Prototype documentation
  issues sorted out first (transferring the old doc to the new format
  and updating), since that's more urgent.
 
  -- T.J. :-)
 
  On Sep 5, 2:46 pm, Allen Madsen bla...@gmail.com wrote:
 
 
 
 var Thingy = Class.create({
 nifty: function nifty(foo, bar) {
 nifty.$super.call(this, foo);
 }
 });
 
 It just ignores the function name and complains that 'nifty' is not
 defined.  This works:
 
   I think you need this.nifty.$super.call(this, foo);
 
   Allen Madsenhttp://www.allenmadsen.com
 


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Prototype: Core group.
To post to this group, send email to prototype-core@googlegroups.com
To unsubscribe from this group, send email to 
prototype-core-unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/prototype-core?hl=en
-~--~~~~--~~--~--~---



[Prototype-core] Re: A more efficient $super for Prototype 2

2009-09-06 Thread T.J. Crowder

  I think you need this.nifty.$super.call(this, foo);

 You don't, although that also works.

Ack!  Sorry, too early in the morning, hadn't had enough coffee.

That does *not* work, because you always refer to the bottommost
subclass's nifty (this.nifty is always the bottommost function), so
you end up endlessly recursing.  Wow that's an easy trap to fall into.

No, it's either use the function's name unadorned, or use
arguments.callee and pay the performance penalty.  Personally, I
prefer using the function's name. :-)

-- T.J. :-)

On Sep 6, 8:48 am, T.J. Crowder t...@crowdersoftware.com wrote:
 Hi Allen,

  I think you need this.nifty.$super.call(this, foo);

 You don't, although that also works.  A named function's name is in
 scope within the function:

     function foo(bar) {
         alert(typeof foo); // Alerts function
     }

 However, I was thinking about anonymous functions this morning while
 waking up (pathetic, isn't it?) and realized that even if you don't
 use a named function, you can avoid arguments.callee with exactly the
 form you describe:  this.nifty.$super.call(this, foo);  I don't like
 the repetition of this, but if you don't have time to switch
 everything over to named functions (I'm thinking of retrofitting
 efforts), it's a reasonable first step, and I assume (haven't tested
 it yet) still gets speed gains over arguments.callee.

 Will be posting a sample implementation (it's wonderfully simple, but
 there are a couple of edge cases around dynamic updates of classes)
 and tests ASAP, but I want to get some of the Prototype documentation
 issues sorted out first (transferring the old doc to the new format
 and updating), since that's more urgent.

 -- T.J. :-)

 On Sep 5, 2:46 pm, Allen Madsen bla...@gmail.com wrote:



    var Thingy = Class.create({
        nifty: function nifty(foo, bar) {
            nifty.$super.call(this, foo);
        }
    });

It just ignores the function name and complains that 'nifty' is not
defined.  This works:

  I think you need this.nifty.$super.call(this, foo);

  Allen Madsenhttp://www.allenmadsen.com
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Prototype: Core group.
To post to this group, send email to prototype-core@googlegroups.com
To unsubscribe from this group, send email to 
prototype-core-unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/prototype-core?hl=en
-~--~~~~--~~--~--~---



[Prototype-core] Re: A more efficient $super for Prototype 2

2009-09-04 Thread Robert Kieffer
Hey gang,

I took a look at this issue a while ago, in a blog post that generated a
fair bit of discussion and spin off investigations (see
http://www.google.com/search?q=inheritance+performance+javascript) so I'll
try to weigh in.  However I'm in the middle of an extended road trip, so I
don't have the time/resources necessary to give this proper attention...

http://ejohn.org/blog/simple-javascript-inheritance - JQ's swipe at this
problem.  Definitely read through the comments.  Your approach appears
similar to his (which is based on Dean Edward's Base2).  Dean uses
this.base(), instead of this.callSuper(), fwiw.  no strong opinions there,
although this.base() seems a bit more prototype-like in it's terseness.

The performance tests I did for Base2 (see the broofa.com article in the
google search above) are probably a good first-guess at the performance your
approach will have compared to other techniques.

Technically this doesn't break backward compatibility - $super and
this.callSuper() can coexist as dual techniques for doing inheritance,
correct?  We just need to decide if $super support will continue in P2.

... and, finally, I vaguely recall people raising some interesting edge
cases.  But I don't remember where I saw those.  *sigh*.

- rwk

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Prototype: Core group.
To post to this group, send email to prototype-core@googlegroups.com
To unsubscribe from this group, send email to 
prototype-core-unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/prototype-core?hl=en
-~--~~~~--~~--~--~---



[Prototype-core] Re: A more efficient $super for Prototype 2

2009-09-04 Thread Jim Higson


On Friday 04 September 2009 14:09:32 T.J. Crowder wrote:
 [...] I do _not_ mean that I
 think callSuper is a great name; I don't and I expect suggestions
 like yours to result in a better name.  But something unlikely to
 clash makes it simpler for people to do a global search-and-replace to
 convert $super(...) to this.niftyNameHere(arguments, ...).  

How about this.$super()?

-- 
Jim
my wiki ajaxification thing: http://wikizzle.org
my blog: http://jimhigson.blogspot.com/

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Prototype: Core group.
To post to this group, send email to prototype-core@googlegroups.com
To unsubscribe from this group, send email to 
prototype-core-unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/prototype-core?hl=en
-~--~~~~--~~--~--~---



[Prototype-core] Re: A more efficient $super for Prototype 2

2009-09-04 Thread T.J. Crowder

@Allen  @Jim,

Gets my vote.

-- T.J. :-)

On Sep 4, 3:05 pm, Jim Higson j...@wikizzle.org wrote:
 On Friday 04 September 2009 14:09:32 T.J. Crowder wrote:

  [...] I do _not_ mean that I
  think callSuper is a great name; I don't and I expect suggestions
  like yours to result in a better name.  But something unlikely to
  clash makes it simpler for people to do a global search-and-replace to
  convert $super(...) to this.niftyNameHere(arguments, ...).  

 How about this.$super()?

 --
 Jim
 my wiki ajaxification thing:http://wikizzle.org
 my blog:http://jimhigson.blogspot.com/
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Prototype: Core group.
To post to this group, send email to prototype-core@googlegroups.com
To unsubscribe from this group, send email to 
prototype-core-unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/prototype-core?hl=en
-~--~~~~--~~--~--~---



[Prototype-core] Re: A more efficient $super for Prototype 2

2009-09-04 Thread T.J. Crowder

Hi again folks,

This thread[1] about using Array.prototype.slice to copy arguments
made me wonder whether the speed improvements I found had more to do
with the fact my implementation of the new mechanism had its own copy-
the-args function (which is faster than using `slice` on most
browsers; see the thread for details) than with eliminating calls and
function creation.  And the answer is:  No, but with the important
caveat:  On Chrome when using the callSuper helper, a big part of
the gains were indeed down to the copy-the-args function instead of
`slice`.  If I modify my new mechanism to use `slice` instead (which
obviously is the wrong way 'round, but never mind), when using the
helper the new mechanism is only about 2X faster on Chrome than the
old mechanism.  Of course, Firefox got faster in that scenario (since
Firefox is the one browser in my set of tests where using `slice` is
faster than one's own copy function).

So summing up, the new mechanism remains faster across-the-board even
using the helper, but the gains on Chrome will not be as marked (when
using a helper) as they seem at present because of the difference in
how args are copied.  And of course, one of the great things about the
new mechanism is that you don't have to copy args at all if you are
willing to use the more verbose syntax.

[1] 
http://groups.google.com/group/prototype-core/browse_thread/thread/cf8c287e231a0192#
--
T.J. Crowder
tj / crowder software / com
www.crowdersoftware.com

On Sep 4, 3:09 pm, T.J. Crowder t...@crowdersoftware.com wrote:
 @Allen  @Jim,

 Gets my vote.

 -- T.J. :-)

 On Sep 4, 3:05 pm, Jim Higson j...@wikizzle.org wrote:



  On Friday 04 September 2009 14:09:32 T.J. Crowder wrote:

   [...] I do _not_ mean that I
   think callSuper is a great name; I don't and I expect suggestions
   like yours to result in a better name.  But something unlikely to
   clash makes it simpler for people to do a global search-and-replace to
   convert $super(...) to this.niftyNameHere(arguments, ...).  

  How about this.$super()?

  --
  Jim
  my wiki ajaxification thing:http://wikizzle.org
  my blog:http://jimhigson.blogspot.com/
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Prototype: Core group.
To post to this group, send email to prototype-core@googlegroups.com
To unsubscribe from this group, send email to 
prototype-core-unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/prototype-core?hl=en
-~--~~~~--~~--~--~---



[Prototype-core] Re: A more efficient $super for Prototype 2

2009-09-04 Thread kangax

On Sep 4, 8:15 am, T.J. Crowder t...@crowdersoftware.com wrote:
 Hi all,

 I've come up with a new way of handling $super (which I can't imagine
 is unique, it's just new to me) which is markedly more efficient than
 our current $super on all of the browsers I've tried it on.  I'm
 wondering whether we should consider it for Prototype 2.

Our current solution is clearly one of the slowest inheritance
implementations out there. You get very nice sugar for a very high
price :) No surprises there. I think P2 should definitely employ a
simpler approach (either fully replacing old one or just as a separate
option).

It's worth mentioning that one of the warts of current solution is
that it relies on function decompilation - something that's known to
cause problems [1][2] and is better avoided (fwiw, ES committee didn't
have enough time to handle this issue so ES5 specifies
`Function.prototype.toString` to return the very same *implementation-
dependent* function representation)


 Executive summary:

 Pros -
 * Avoids calling toString on subclass methods when defining classes.
 * Avoids creating closures for each $super-enabled subclass method.
 * Avoids creating an on-the-fly function on every call to a $super-
 enabled method.
 * Avoids at least four extra calls when $super-enabled methods are
 called.
 * Consequently reduces the time to call methods that use $super, from
 markedly (1.6X as fast) to dramatically (10X as fast) depending on
 browser and choices the subclass author makes.
 * Theoretically reduces memory footprint (no added functions/
 closures).
 * Minifiers (like packer3) that change arg names don't break things by
 renaming $super.
 * (Subjective) Simpler code in Class.create for contribs to
 understand.

 Cons -
 * Breaks backward compatibility.
 * Syntax for calling the $super method is slightly more complex.

  * Relies on `arguments.callee` with all the consequences.

To explain consequences:

`arguments.callee` is considered one of the warts of ES3. Besides
certain security concerns, the bad part of it is that it requires
creation of `arguments` object (when entering execution context). This
creation is rather expensive and results in both - memory and perf.
hits. Some of the modern implementations optimize in such way that
they only create `arguments` object when it statically occurs in a
function body (or when there's a chance of dynamic evaluation, such as
`eval`, `setTimeout` occurrence, etc.). Others create `arguments`
object on first resolution of `arguments` identifier, etc.

You can easily see it by yourself. Create 2 identical functions, one
of which would use `arguments.callee` and another - plain identifier;
then look at a difference.

ES5 also introduces strict mode. When in strict mode,
`argument.callee` throws TypeError on access. IIRC, Caja (secure
subset of ES) and some of its variations (Cajita, Valija), emulate ES5-
strict behavior and also throw error. If something in Prototype were
to rely on `arguments.callee`, it would effectively prevent running it
in strict mode or cajoling it.

[snip current approach explanation]

 Here's how the new approach works:

 1. At class definition time, Class.create detects that the subclass
 overrides the superclass's method (this is a trivial property check)
 and, if so, stores a reference to the super's function as a property
 called $super on the sub's function object.

 2. When a method is called, there is no indirection, the call goes
 direct to the subclass's defined method.  The subclass can then call
 the super's version via arguments.callee.$super.

 The unaided syntax subclass methods would use to call the super's
 version is complicated and error-prone (to the novice, anyway):

 nifty: function(foo, bar) {
 arguments.callee.$super.call(this, foo);
 }

 ...and so this solution envisions a helper callSuper method (name
 TBD) authors may choose to use instead (at the cost of an extra
 function call):

 nifty: function(foo, bar) {
 this.callSuper(arguments, foo);
 }

 You can see why I think a helper may be useful; that's quite a lot
 simpler.  Note that the first argument is always 'arguments' and does
 *not* mean #callSuper is passing all of the arguments to the super
 function; you follow it with the arguments you want to pass.  We can
 muck about with the API on the helper, and of course class authors can
 create their own for their own needs.

I usually use a similar approach instead of `$super`, which I first
saw mentioned by Tobie some time ago:

Class.Methods.callSuper = function(methodName) {
  var fn = this.constructor.superclass.prototype[methodName];
  return (arguments.length  1)
? fn.apply(this, _slice.call(arguments, 1))
: fn.call(this);
}

then:

initialize: function(options) {
  ...
  this.callSuper('initialize', options);
  ...
}

One huge downside to this is that there's now repetition of method
name. If I change method name, I also have to remember to change first

[Prototype-core] Re: A more efficient $super for Prototype 2

2009-09-04 Thread T.J. Crowder

Hi Juriy,

Thanks for that.  Yes, it was the function decompilation (and the on-
the-fly bind) that made me look for another solution.

I was unaware of the performance implication of arguments.callee, and
*WOW* does it make a speed difference (see below).  The good thing is
that this solution doesn't require arguments.callee (we'll have to
adjust the helper, or do away with it).  Just name your functions and
use the name.  You _can_ use arguments.callee if you like, but for
best results, use function names.

Because **HOLY COW** what a difference that makes.  Using the
function's name instead makes the new mechanisn 16-50X faster (I kid
you not) than the old on Chrome.  Firefox also goes through the roof
speed-wise, we're talking 35X+.  Even IE is more impressed, going from
1.6X to 2.4X as fast.  Opera says yes, please with a 11X
improvement, as does Safari with 10X.

The fly in the ointment is that IE will not acknowledge the function
name if defined as part of an assignment/initialization statement like
so:

var Thingy = Class.create({
nifty: function nifty(foo, bar) {
nifty.$super.call(this, foo);
}
});

It just ignores the function name and complains that 'nifty' is not
defined.  This works:

var Thingy = Class.create((function() {
function nifty(foo, bar) {
nifty.$super.call(this, foo);
}

return {nifty: nifty};
})());

(Which is what a lot of the Prototype source now does.)  So that's a
larger impact on how you define classes, but also suggests a useful
pattern to authors for sharing common private class methods/data
within the closure, and WOW what a performance difference.

There seems to be enough interest in this that it's worth my doing a
sample changeset with test cases and sharing it 'round; I'll do that
over the weekend.
--
T.J. Crowder
tj / crowder software / com
www.crowdersoftware.com


On Sep 4, 6:25 pm, kangax kan...@gmail.com wrote:
 On Sep 4, 8:15 am, T.J. Crowder t...@crowdersoftware.com wrote:

  Hi all,

  I've come up with a new way of handling $super (which I can't imagine
  is unique, it's just new to me) which is markedly more efficient than
  our current $super on all of the browsers I've tried it on.  I'm
  wondering whether we should consider it for Prototype 2.

 Our current solution is clearly one of the slowest inheritance
 implementations out there. You get very nice sugar for a very high
 price :) No surprises there. I think P2 should definitely employ a
 simpler approach (either fully replacing old one or just as a separate
 option).

 It's worth mentioning that one of the warts of current solution is
 that it relies on function decompilation - something that's known to
 cause problems [1][2] and is better avoided (fwiw, ES committee didn't
 have enough time to handle this issue so ES5 specifies
 `Function.prototype.toString` to return the very same *implementation-
 dependent* function representation)







  Executive summary:

  Pros -
  * Avoids calling toString on subclass methods when defining classes.
  * Avoids creating closures for each $super-enabled subclass method.
  * Avoids creating an on-the-fly function on every call to a $super-
  enabled method.
  * Avoids at least four extra calls when $super-enabled methods are
  called.
  * Consequently reduces the time to call methods that use $super, from
  markedly (1.6X as fast) to dramatically (10X as fast) depending on
  browser and choices the subclass author makes.
  * Theoretically reduces memory footprint (no added functions/
  closures).
  * Minifiers (like packer3) that change arg names don't break things by
  renaming $super.
  * (Subjective) Simpler code in Class.create for contribs to
  understand.

  Cons -
  * Breaks backward compatibility.
  * Syntax for calling the $super method is slightly more complex.

   * Relies on `arguments.callee` with all the consequences.

 To explain consequences:

 `arguments.callee` is considered one of the warts of ES3. Besides
 certain security concerns, the bad part of it is that it requires
 creation of `arguments` object (when entering execution context). This
 creation is rather expensive and results in both - memory and perf.
 hits. Some of the modern implementations optimize in such way that
 they only create `arguments` object when it statically occurs in a
 function body (or when there's a chance of dynamic evaluation, such as
 `eval`, `setTimeout` occurrence, etc.). Others create `arguments`
 object on first resolution of `arguments` identifier, etc.

 You can easily see it by yourself. Create 2 identical functions, one
 of which would use `arguments.callee` and another - plain identifier;
 then look at a difference.

 ES5 also introduces strict mode. When in strict mode,
 `argument.callee` throws TypeError on access. IIRC, Caja (secure
 subset of ES) and some of its variations (Cajita, Valija), emulate ES5-
 strict behavior and also throw error. If something in Prototype