[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  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  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 kangax



On Sep 9, 7:29 am, "T.J. Crowder"  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 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  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. Crowder 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  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  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 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. Crowder 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  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 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  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 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 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 T.J. Crowder

@kangax, @tobie:

*sigh*  The "name" property _was_ in the November '08 draft (sect.
15.3.5.4), I didn't realize they'd taken it out again, but apparently
they have, it's not in the April candidate spec (which has now
replaced the November draft in my reference folder).

@kangax:

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

You're right, at least the version linked by Robert does.  I missed
that initially because it's an implicit conversion when passing the
function into a regex.  It also happily assumes that if "_super"
appears anywhere in the method -- inside a string, as a variable name,
whatever -- that you want the supercall magic wrapped around it.
Finally, it tests if function decompilation works and if it doesn't,
the implementation wraps the magic around *all* methods.

@Robert:

> > 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?

Initially it was the API, I didn't like passing the superfunction in
as an argument.  That lead to my looking at the implementation behind
it.

-- T.J. :-)


On Sep 8, 11:02 pm, Robert Kieffer  wrote:
> On Tue, Sep 8, 2009 at 1:21 PM, T.J. Crowder  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-08 Thread Robert Kieffer
On Tue, Sep 8, 2009 at 1:21 PM, T.J. Crowder  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-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 kangax



On Sep 8, 11:11 am, Robert Kieffer  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

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, 12:25 pm, "T.J. Crowder"  wrote:
> 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)...

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

[...]

--
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 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  wrote:
> On Sep 8, 8:44 am, "T.J. Crowder"  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 Allen Madsen

Robert,

I use super heavily in many of my applications and it isn't something
trivial to just add it on to prototype's class. I would be very
against it. As long as it is clearly documented then I don't see a
problem. I spend a good deal of time in #prototype and a majority of
the questions are around selector's or the AJAX stuff. From my
experience most newbies don't even use Class.

Allen Madsen
http://www.allenmadsen.com



On Tue, Sep 8, 2009 at 2:43 PM, Robert Kieffer wrote:
>
> On Sep 8, 8:44 am, "T.J. Crowder"  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 Robert Kieffer

On Sep 8, 8:44 am, "T.J. Crowder"  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 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  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  
> 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  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  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 funct

[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  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  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  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 th

[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  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

[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  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  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

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 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 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  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
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  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 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"  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  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
>> >
>> > > 
>> > > 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()
>> > > 
>> >
>> > > 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  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"  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  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
> >
> > > 
> > > 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()
> > > 
> >
> > > 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 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"  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  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
>
> > 
> > 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()
> > 
>
> > 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 T.J. Crowder

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/db9ccdaae4f7f705/c84a73f979fafc2c?#c84a73f979fafc2c

-- T.J.

On Sep 8, 1:03 pm, Radoslav Stankov  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
>
> 
> 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()
> 
>
> 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 Radoslav Stankov

"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


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()


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 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  wrote:
> 2009/9/8 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  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=ZEND002498&r=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 Richard Quadling

2009/9/8 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  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=ZEND002498&r=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,

> 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  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 :
>
> 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"  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  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

[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 T.J. Crowder

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"  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  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 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  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 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-07 Thread T.J. Crowder

Hi Allen,

> I guess I don't understand why it wouldn't work.

Yeah, it's...subtle. :-)  It runs into what I call the "grandchild"
problem.  Consider Parent < Child < GrandChild, all with #nifty
functions:

var Parent = Class.create((function() {

function nifty(spiffy)
{
return "P(" + spiffy + ")";
}

return {
nifty: nifty
};
})());
var Child = Class.create(Parent, (function() {

function nifty(spiffy)
{
return nifty.$super.call(this, spiffy) + " < C";
}

return {
nifty: nifty
};
})());
var GrandChild = Class.create(Child, (function() {

function nifty(spiffy)
{
return nifty.$super.call(this, spiffy) + " < GC";
}

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

We instantiate a GrandChild instance and call GrandChild#nifty:

var gc = new GrandChild();
gc.nifty('cool');

Inside our methods, "this" always refers to the actual instance, and
so "this.nifty" always refers to the "nifty" function referenced by
the instance, which is always GrandChild#nifty.  So within
GrandChild#nifty, this.nifty.$super will reference Child#nifty and
using that form will work -- but only one level deep.  Because then
within Child#nifty, if we use this.nifty.$super, nothing is diffrent
-- "this" still refers to the instance, and so "this.nifty" still
refers to GrandChild#nifty, and so "this.nifty.$super" still refers to
Child#nifty.  If Child#nifty calls this.nifty.$super, it will call
itself and recurse.

Another way to say that is that within the various #nifty functions,
"this.nifty !== nifty" except at the bottom (GrandChild) level.

The reason that the syntax without "this" works is that the name of a
function is in scope within the function, and it refers to *that
specific function*.  So an unadorned "nifty" within GrandChild#nifty
refers to GrandChild#nifty, within Child#nifty refers to Child#nifty,
and within Parent#nifty refers to Parent#nifty.  So "nifty.
$super" (without "this") always gives us our super function.

I'm posting an implementation (it was really easy to mod the source to
support this, including handling dynamic changes to the hierarchy) and
unit tests in a little bit.

-- T.J. :-)

On Sep 8, 3:57 am, 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
>   }
>
> });
>
> 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 Madsenhttp://www.allenmadsen.com
>
>
>
> On Sun, Sep 6, 2009 at 5:38 AM, T.J. Crowder  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"  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  wrote:
>
> >

[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  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"  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  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 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  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"  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  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"  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  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

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  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-05 Thread Allen Madsen
>
> >
> > 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 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-04 Thread kangax



On Sep 4, 2:54 pm, "T.J. Crowder"  wrote:
> 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.

Sounds good.

>
> 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.

Told ya :)

>
> 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:

That's a so-called "named function expression".

>
>     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:

This is strange. IE should parse `nifty` as a *function declaration*
in this case, and make available in the enclosing scope (against
specs). I don't see why `nifty` identifier would not be available in a
function. Take a look at my NFE article -  - for all the gory details about this
particular IE idiocy (and a little more on the same subject) :)

>
>     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.

Yep, giving function an identifier is quite helpful in debugging/
profiling, or even plain introspection in console.

>
> 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.

Great! Thanks.

[...]

--
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-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  wrote:
> On Sep 4, 8:15 am, "T.J. Crowder"  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-
> str

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

2009-09-04 Thread kangax

On Sep 4, 8:15 am, "T.J. Crowder"  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

[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"  wrote:
> @Allen & @Jim,
>
> Gets my vote.
>
> -- T.J. :-)
>
> On Sep 4, 3:05 pm, Jim Higson  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

@Allen & @Jim,

Gets my vote.

-- T.J. :-)

On Sep 4, 3:05 pm, Jim Higson  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 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 Allen Madsen
Hi,
I think the speed improvement definitely merits going into. I would suggest
the helper be called $super so when converting, the relationship is evident.
I have to admit that passing arguments in feels odd to me though.

Allen Madsen
http://www.allenmadsen.com


On Fri, Sep 4, 2009 at 9:09 AM, T.J. Crowder  wrote:

>
> Hi Richard,
>
> Thanks for that.
>
> I like the terseness and clarity of this.base() although I'd have
> concerns about that making it difficult for people to retrofit their
> classes ("base" being a fairly common word).  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, ...).  Even in a
> large project, that should be a 10-minute exercise.
>
> Agreed that both mechanisms can co-exist, except that I -- perhaps
> unreasonably -- find running all of the subclass methods through
> Function#toString at definition time ugly.  But you're right, once
> deprecated the old $super could be supported for a dot rev or so to
> ease transition.
>
> I meant to mention in my earlier post that once implementations have a
> native Function#bind (which I'm sure everyone knows is in the latest
> ECMA draft specs), presumably the cost of that bind-on-each-method-
> call would go down, though I suspect it will never reduce to zero.
> --
> T.J. Crowder
> tj / crowder software / com
> www.crowdersoftware.com
>
>
> On Sep 4, 1:53 pm, Robert Kieffer  wrote:
> > 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 (seehttp://
> 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 T.J. Crowder

Hi Richard,

Thanks for that.

I like the terseness and clarity of this.base() although I'd have
concerns about that making it difficult for people to retrofit their
classes ("base" being a fairly common word).  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, ...).  Even in a
large project, that should be a 10-minute exercise.

Agreed that both mechanisms can co-exist, except that I -- perhaps
unreasonably -- find running all of the subclass methods through
Function#toString at definition time ugly.  But you're right, once
deprecated the old $super could be supported for a dot rev or so to
ease transition.

I meant to mention in my earlier post that once implementations have a
native Function#bind (which I'm sure everyone knows is in the latest
ECMA draft specs), presumably the cost of that bind-on-each-method-
call would go down, though I suspect it will never reduce to zero.
--
T.J. Crowder
tj / crowder software / com
www.crowdersoftware.com


On Sep 4, 1:53 pm, Robert Kieffer  wrote:
> 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 
> (seehttp://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 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
-~--~~~~--~~--~--~---