RE: ES4 draft: Function
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
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
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
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
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
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
-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
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
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
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
-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
-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
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
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