RE: ES4 draft: Function

2008-03-17 Thread Lars Hansen
Draft 2 of the spec for the Function class.  Changelog near the
beginning; several small changes only.

--lars 
Title: The class "Function"




 The class Function 



NAME:   "The class 'Function'"
FILE:   spec/library/Function.html
CATEGORY:   Pre-defined classes  (E262-3 Chapter 15)
SOURCES:REFERENCES [1], [2], [3], [5]
SPEC AUTHOR:Lars
DRAFT STATUS:   DRAFT 2 - 2008-03-14
REVIEWED AGAINST ES3:   YES
REVIEWED AGAINST ERRATA:YES
REVIEWED AGAINST BASE DOC:  YES
REVIEWED AGAINST PROPOSALS: YES
REVIEWED AGAINST CODE:  YES
REVIEWED AGAINST TICKETS:   YES
IMPLEMENTATION STATUS:  ES4RI
TEST CASE STATUS:   ?


CHANGES SINCE DRAFT 1 (2008-03-10)

  * The 'thisObj' parameter to 'bind' is no longer optional, it must
be an object (not null).

  * Removed the "Implementation" section for the 'meta::invoke' method
(it added nothing).

  * Replaced note about host functions being "anything" with a
paragraph about the type 'Callable'.

OPEN ISSUES

  * ES3 restrictions on argArray having to be an Array or an arguments
object in Function.prototype.apply have been removed here.

  * Is it reasonable to allow the thisObj parameter to bind to be null
(so that it defaults to the global object of the bind function)?


NOTES

  * The use of 'Private' instead of 'private' below is a workaround
for a bug in the reference implementation (#368).


REFERENCES

[1] ECMAScript 3rd Edition specification section 15.3
[2] http:wiki.ecmascript.org/doku.php?id=proposals:static_generics
[2] http:bugs.ecmascript.org/ticket/172
[4] http:bugs.ecmascript.org/ticket/173
[5] http:bugs.ecmascript.org/ticket/174




 The class Function is a dynamic, non-final, direct subclass of
Object (see class Object).

 All objects defined by function definitions or expressions in
ECMAScript are instances of the class Function.

 Not all objects that can be called as functions are instances of
subclasses of the Function class, however.  Any object that has a
meta::invoke property can be called as a function.

 The structural type Callable (see type:Callable) 
matches every object that has a meta::invoke property.


Synopsis

 The class Function provides the following interface:


dynamic class Function extends Object
{
public function Function(...args) 
static meta function invoke(...args) 

static public function apply(fn: Callable, thisArg: Object=null, argArray: Object=null) 
static public function bind(method: Callable, thisObj: Object, ...args) 
static public function call(fn: Callable, thisObj: Object=null, ...args) 

static public const length = 1

meta final function invoke(  ) 

override intrinsic function toString() : string 

intrinsic function apply(thisArg: Object=null, argArray: Object=null) 
intrinsic function bind(thisObj: Object, ...args) 
intrinsic function call(thisObj: Object=null, ...args) 

public const length = 
public var   prototype = 
}


The Function prototype object provides these direct properties:


meta::invoke: function () 
length:   0
toString: function () 
apply:function(thisArg, argArray) 
bind: function(thisArg, ...args) 
call: function(thisArg, ...args) 



Methods on the Function class object

 new Function (p1, p2,  , pn, body) 

Description  When the Function constructor is called with some arguments
as part of a new _expression_, it creates a new Function
instance whose parameter list is given by the concatenation of the
pi arguments separated by "," and whose executable code
is given by the body argument.

 There may be no pi arguments, and body is optional too,
defaulting to the empty string.

 If the first character of the comma-separated concatenation of the
pi is a left parenthesis then the list of parameters
must be parseable as a FormalParameterListopt enclosed
in parentheses and optionally followed by a colon and a return type.

 Otherwise, the list of parameters must be parsable as a
FormalParameterListopt.

 If the list of parameters is not parseable as outlined in the
previous two paragraphs, or if the body is not parsable as a
FunctionBody, then a SyntaxError exception is thrown (see the
grammar in section ECMAScript grammar).

 Regardless of the form of the parameter list, it may include type
annotations, default parameter values, and rest arguments.

Returns  The Function constructor returns a new Function instance.

Implementation

public function Function(...args)
helper::createFunction(args);

helper function createFunction(args) {
let parameters = "";
let body = "";
if (args.length > 0) {
body = args[args.length-1];
args.length = args.length-1;
parameters = args.join(",");
}
body = string(body);
magic::initializeFunction(this, __ES4__::global, parameters, body);
}


 The magic function 

Re: ES4 draft: Function

2008-03-13 Thread Dominic Cooney
Why doesn't Function have something like apply that does the same as
in a new expression, i.e. allocate-init-and-apply? To put it another
way: given arguments in an array, I want to write:

F.thisThing(args) and have it mean the same as new F(args[0], args[1],
... args[n-1])

Or is what happens behind the veil of object creation detailed enough
that I can write a facsimile of it with apply? I guess something like:

var x = {};
x.prototype = F.prototype;
x = F.apply(x, args) || x;

But why force me to guess? No doubt I am wrong.

Dominic

On Mon, Mar 10, 2008 at 7:38 PM, Jon Zeppieri [EMAIL PROTECTED] wrote:
 On 3/10/08, Lars Hansen [EMAIL PROTECTED] wrote:
   First draft of the spec for the Function class.  Please comment.
  

  Suggestion: deprecate the Function constructor and static invoke().

  Almost all of its uses are better handled by function expressions and,
  in those cases where eval() in required, one can use eval().

  -Jon


 ___
  Es4-discuss mailing list
  Es4-discuss@mozilla.org
  https://mail.mozilla.org/listinfo/es4-discuss

___
Es4-discuss mailing list
Es4-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es4-discuss


Re: ES4 draft: Function

2008-03-13 Thread Garrett Smith
Hi Dustin,

Well it does, apparently it was called the splat operator, which (to
me) sounds a better than spread. I think it works like:-

var args = [12, true];
new C(...args);

function C( count, isSemiAnnual) {

}

- Maybe one of guys writing the specs can comment on that.


It can be hacked in ES3:-

/**
 * @param {Function} fun constructor to be invoked.
 * @param {Array} args arguments to pass to the constructor.
 * Instantiates a constructor and uses apply().
 */
newApply : function(fun, args) {
if(arguments.length === 0) return;
var f = arguments.callee, i;

f.prototype = fun.prototype;// Copy prototype.
f.prototype.constructor = fun;

i = new f;
fun.apply(i, args); // Apply the original constructor.
return i;
},

- from http://dhtmlkitchen.com/ape/build/APE.js

Garrett

On Thu, Mar 13, 2008 at 10:48 AM, Dominic Cooney
[EMAIL PROTECTED] wrote:
 Why doesn't Function have something like apply that does the same as
  in a new expression, i.e. allocate-init-and-apply? To put it another
  way: given arguments in an array, I want to write:

  F.thisThing(args) and have it mean the same as new F(args[0], args[1],
  ... args[n-1])

  Or is what happens behind the veil of object creation detailed enough
  that I can write a facsimile of it with apply? I guess something like:

  var x = {};
  x.prototype = F.prototype;
  x = F.apply(x, args) || x;

  But why force me to guess? No doubt I am wrong.

  Dominic



  On Mon, Mar 10, 2008 at 7:38 PM, Jon Zeppieri [EMAIL PROTECTED] wrote:
   On 3/10/08, Lars Hansen [EMAIL PROTECTED] wrote:
 First draft of the spec for the Function class.  Please comment.

  
Suggestion: deprecate the Function constructor and static invoke().
  
Almost all of its uses are better handled by function expressions and,
in those cases where eval() in required, one can use eval().
  
-Jon
  
  
   ___
Es4-discuss mailing list
Es4-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es4-discuss
  
  ___
  Es4-discuss mailing list
  Es4-discuss@mozilla.org
  https://mail.mozilla.org/listinfo/es4-discuss

___
Es4-discuss mailing list
Es4-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es4-discuss


Re: ES4 draft: Function

2008-03-13 Thread Dominic Cooney
Neat! Thanks for the link.

Dominic

On Thu, Mar 13, 2008 at 10:58 AM, Jon Zeppieri [EMAIL PROTECTED] wrote:
 On Thu, Mar 13, 2008 at 1:48 PM, Dominic Cooney
  [EMAIL PROTECTED] wrote:
   Why doesn't Function have something like apply that does the same as
in a new expression, i.e. allocate-init-and-apply? To put it another
way: given arguments in an array, I want to write:
  
F.thisThing(args) and have it mean the same as new F(args[0], args[1],
... args[n-1])

  How about the proposed spread/spat(...) operator :
new F(...args)

  http://bugs.ecmascript.org/ticket/357

  -Jon

___
Es4-discuss mailing list
Es4-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es4-discuss


Re: ES4 draft: Function

2008-03-13 Thread Waldemar Horwat
I agree with Lars on this issue for exactly the same reasons as what he stated.

Waldemar
___
Es4-discuss mailing list
Es4-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es4-discuss


Re: ES4 draft: Function

2008-03-13 Thread Waldemar Horwat
Here are my comments on this section:


 static public function apply(fn /*: function*/, thisArg: Object=null, 
 argArray: Object=null)
 static public function bind(method /*: function*/, thisObj: Object=null, 
 ...args)
 static public function call(fn /*: function*/, thisObj: Object=null, ...args)
 prototype function apply(/*this: function, */ thisArg=undefined, 
 argArray=undefined)
 prototype function bind(/*this: function, */ thisObj=undefined, ...args)
 prototype function call(/*this: function, */ thisObj=undefined, ...args)

What does /*: function*/ mean here?  Are these arguments required to have the 
function type or not?


Although apply is redundant in the presence of the splat operator, I see no 
harm in keeping it for consistency with ES3.


 *Implementation*
 
 The implementation of the meta function |invoke| is 
 implementation-dependent.

Omit the implementation section altogether.  Saying implementation-dependent 
is misleading here, as its behavior should not be implementation-dependent.


 intrinsic function apply(thisArg: Object=null, argArray: Object=null)
 Function.apply(this, thisArg, argArray);

 intrinsic function bind(thisObj: Object=null, ...args)
 Function.helper::bind(this, thisObj, args);

 intrinsic function call(thisObj: Object=null, ...args)
 Function.apply(this, thisObj, args);

The middle one is not like the other two.  Hmmm  another use case for the 
splat operator.


Waldemar
___
Es4-discuss mailing list
Es4-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es4-discuss


RE: ES4 draft: Function

2008-03-11 Thread Lars Hansen
 -Original Message-
 From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On 
 Behalf Of Jon Zeppieri
 Sent: 10. mars 2008 20:39
 To: Lars Hansen
 Cc: es4-discuss Discuss
 Subject: Re: ES4 draft: Function
 
 On 3/10/08, Lars Hansen [EMAIL PROTECTED] wrote:
  First draft of the spec for the Function class.  Please comment.
 
 
 Suggestion: deprecate the Function constructor and static invoke().
 
 Almost all of its uses are better handled by function 
 expressions and, in those cases where eval() in required, one 
 can use eval().

I think there are three points to be made here.  The first is 
that the Function constructor provides functionality that 
eval does not, namely, creating new functions that are closed 
in the global environment only.  Erik made the
argument that this is sometimes useful; I agree.

The second point is about deprecation.  TG1 has had a difficult 
time with deprecation in general.  It is not clear that 
deprecation means anything on the web, except /maybe/ in the 
very long term.  The fact that we deprecate something has 
no bearing on existing content, and new engines will need 
to support old behavior.  So though TG1 finally (on my 
insistence) deprecated the arguments object, it was with
a shrug, and it would be surprising to me if the deprecation
clause makes it into the final spec, as it has no real impact.
(I actually wanted to remove the arguments object from ES4
so that ES4-only implementations would not have to implement
it at all, to be replaced by rest arguments and this function.)

The third point is, why deprecate that particular functionality?
It's not like it costs much at all in terms of spec space or
implementation complexity.  Eval already requires hooks into a
run-time compiler, which is where the heavy lifting goes.

--lars
___
Es4-discuss mailing list
Es4-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es4-discuss


Re: ES4 draft: Function

2008-03-11 Thread Jon Zeppieri
On Tue, Mar 11, 2008 at 10:49 AM, Lars Hansen [EMAIL PROTECTED] wrote:

  I think there are three points to be made here.  The first is
  that the Function constructor provides functionality that
  eval does not, namely, creating new functions that are closed
  in the global environment only.  Erik made the
  argument that this is sometimes useful; I agree.

Doesn't global.eval() meet this requirement?  From the overview document:

===
ES4 additionally defines eval as a function bound in the global
environment that can be called indirectly
through that environment (e.g., as window.eval(s) in a web browser) or
whose value can be read and
passed around, stored in other variables and so on, and called as a
plain function:
 var e = eval
 ...
 e(myprog)
In both of these cases, the evaluation takes place in the global
environment in which the eval function is
defined.
===


  The second point is about deprecation.  TG1 has had a difficult
  time with deprecation in general.  It is not clear that
  deprecation means anything on the web, except /maybe/ in the
  very long term.  The fact that we deprecate something has
  no bearing on existing content, and new engines will need
  to support old behavior.

Deprecation isn't solely (or even primarily) for the benefit of
implementors.  It tells the programmer: This probably isn't what you
want, and even if it does what you want, there's a more sane way to do
it.

What does new Function() get you that eval doesn't (taking into
consideration global.eval())?  For the most part, it's just
syntactic... well, not sugar, because it doesn't actually result in a
cleaner syntactic construction.  'Syntactic salt' still suggests some
kind of enhancement...  I'd call it a syntactic booger.

To the extent that it isn't just a special case of eval(), it's
useless.  You could, for example, define a subclass of Function that
might do something potentially useful.  I notice that you can't
instrument the normal call functionality, since the instance version
of meta::invoke() is final, but you might be able to instrument
apply() for some potentially useful debugging purpose.  But to make
use of it, you would need to construct your functions using 'new' and
incur the enormous performance penalty -- not to mention the fact that
since all functions so created are closed in the global environment,
it's completely worthless for functions that need to close over
lexical bindings.


 So though TG1 finally (on my
  insistence) deprecated the arguments object, it was with
  a shrug, and it would be surprising to me if the deprecation
  clause makes it into the final spec, as it has no real impact.
  (I actually wanted to remove the arguments object from ES4
  so that ES4-only implementations would not have to implement
  it at all, to be replaced by rest arguments and this function.)

I sympathize.


  The third point is, why deprecate that particular functionality?
  It's not like it costs much at all in terms of spec space or
  implementation complexity.  Eval already requires hooks into a
  run-time compiler, which is where the heavy lifting goes.

Again -- this isn't for the benefit of implementors.


-Jon



  --lars


___
Es4-discuss mailing list
Es4-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es4-discuss


Re: ES4 draft: Function

2008-03-11 Thread Jon Zeppieri
I promise not to drag out this discussion, since no one else seems to
be interested in it.

On Tue, Mar 11, 2008 at 12:16 PM, Lars Hansen [EMAIL PROTECTED] wrote:

  Sure, nobody argues about that per se, but I don't see the spec
  as being the place to take an ideological stand about whether
  global.eval is cleaner than 'new Function', if taking a stand
  doesn't gain practical implementations anything at all.

I'm not trying to make an ideological stand -- or, at least, not a
particularly controversial one.  I put far too much stress on syntax
in my last message.  The more important objection to 'new Function'
concerns its semantics.  The Function constructor has an awkward
status in the language. Most objects are constructed by calling a
constructor or by using a literal syntax, the semantics of which can
be specified in terms of constructor call + accessor calls.  E.g.:

[a, b] has the same semantics as
let (t = new Array()) (t[0] = a, t[1] = b, t)

...whereas you cannot, in the general case, *locally* rewrite a
function expression in terms of 'new Function.'  Also, there's the
point I did raise in my last message: while you can subclass function,
there doesn't appear to be much point in actually doing so --
precisely because most function construction does not go through the
Function constructor.


 The reality
  is that 'new Function' and 'arguments' are available in all
  implementations, they are in wide-spread use, and their use will
  be propagated as long as implementations support them.  Maybe if
  they are deprecated in the spec their use will see some
  decline; maybe ditto if better, alternative features are added
  to the language.  I have more faith in the latter than in the
  former.

These options aren't mutually exclusive, and I don't see the harm in
deprecating this stuff.  Now, if someone will offer a defense of 'new
Function,' that's a different story.  I am not trying to be
controversial here.


  I don't really care about 'new Function' as it's just another
  API to functionality that will exist anyway, and 'new Function' is
  comparatively clean -- I don't agree that it is significantly less
  sane than global.eval.  But I and others do care about 'arguments',
  so we have rest arguments and 'this function'; we do care about the
  operator form of 'eval', so there's been some discussion about
  whether to simply outlaw its use inside classes.  These are better
  ways to make progress than paper deprecation, IMO.

No question that 'arguments' is a more important issue.

-Jon



  --lars


 ___
  Es4-discuss mailing list
  Es4-discuss@mozilla.org
  https://mail.mozilla.org/listinfo/es4-discuss


___
Es4-discuss mailing list
Es4-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es4-discuss


Re: ES4 draft: Function

2008-03-10 Thread Erik Arvidsson
What is the reason to make the thisObj param to bind optional?

2008/3/10 Lars Hansen [EMAIL PROTECTED]:
 First draft of the spec for the Function class.  Please comment.

  --lars

 ___
  Es4-discuss mailing list
  Es4-discuss@mozilla.org
  https://mail.mozilla.org/listinfo/es4-discuss





-- 
erik
___
Es4-discuss mailing list
Es4-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es4-discuss


RE: ES4 draft: Function

2008-03-10 Thread Lars Hansen
 -Original Message-
 From: Erik Arvidsson [mailto:[EMAIL PROTECTED] 
 Sent: 10. mars 2008 17:31
 To: Lars Hansen
 Cc: es4-discuss Discuss
 Subject: Re: ES4 draft: Function
 
 What is the reason to make the thisObj param to bind optional?

Symmetry with call and apply and a consequence of the 
definition given in the proposals page (link below, it's
near the bottom).  But I agree that it seems misguided.  
Will change this unless there's opposition to it.

http://wiki.ecmascript.org/doku.php?id=proposals:static_generics

--lars


 
 2008/3/10 Lars Hansen [EMAIL PROTECTED]:
  First draft of the spec for the Function class.  Please comment.
 
   --lars
 
  ___
   Es4-discuss mailing list
   Es4-discuss@mozilla.org
   https://mail.mozilla.org/listinfo/es4-discuss
 
 
 
 
 
 --
 erik
 
___
Es4-discuss mailing list
Es4-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es4-discuss


RE: ES4 draft: Function

2008-03-10 Thread Lars Hansen
 -Original Message-
 From: [EMAIL PROTECTED] 
 [mailto:[EMAIL PROTECTED] On Behalf Of Lars Hansen
 Sent: 10. mars 2008 18:46
 To: Erik Arvidsson
 Cc: es4-discuss Discuss
 Subject: RE: ES4 draft: Function
 
  -Original Message-
  From: Erik Arvidsson [mailto:[EMAIL PROTECTED]
  Sent: 10. mars 2008 17:31
  To: Lars Hansen
  Cc: es4-discuss Discuss
  Subject: Re: ES4 draft: Function
  
  What is the reason to make the thisObj param to bind optional?
 
 Symmetry with call and apply and a consequence of the 
 definition given in the proposals page (link below, it's near 
 the bottom).  But I agree that it seems misguided.  
 Will change this unless there's opposition to it.
 
 http://wiki.ecmascript.org/doku.php?id=proposals:static_generics

But is null an acceptable non-default value for thisObj (meaning, use
the global object in the bind method's scope)?

--lars
___
Es4-discuss mailing list
Es4-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es4-discuss


Re: ES4 draft: Function

2008-03-10 Thread Jon Zeppieri
On 3/10/08, Lars Hansen [EMAIL PROTECTED] wrote:
 First draft of the spec for the Function class.  Please comment.


Suggestion: deprecate the Function constructor and static invoke().

Almost all of its uses are better handled by function expressions and,
in those cases where eval() in required, one can use eval().

-Jon
___
Es4-discuss mailing list
Es4-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es4-discuss


Re: ES4 draft: Function

2008-03-10 Thread Jon Zeppieri
On 3/10/08, Erik Arvidsson [EMAIL PROTECTED] wrote:
 There are valid use cases for new Function (...) and Function(...).
  One that comes to mind is getting an attribute in DOM and make it into
  an event handler.  Yes, the Function constructor and meta::invoke can
  be replaced by eval but Function needs to be there for ES3
  compatibility.

...which is why I wrote deprecate, rather than remove.  In other
words, I'm suggesting treating the Function constructor the way we're
treating Function.arguments.
___
Es4-discuss mailing list
Es4-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es4-discuss