Re: __doc__ for functions, classes, objects etc.
On 31.08.2011 18:38, Allen Wirfs-Brock wrote: On Aug 31, 2011, at 1:57 AM, Dmitry A. Soshnikov wrote: On 30.08.2011 20:39, Allen Wirfs-Brock wrote: On Aug 30, 2011, at 12:39 AM, Dmitry A. Soshnikov wrote: OK, let's up the topic. Seems there are no technical issues in the proposed thing -- we can simply either accept it or not. The question is whether it's needed and sound proposal and the feature to have in ECMAScript. There certainly are technical issues. To start, by making this part of the core language you would be defining a feature that can be used by any application code. For example, a program might choose to encode essential runtime metadata as its documentation. Because of that possibility, the [[Documentation]] information must always be available at runtime. Minimizers or obfuscators could not remote documentation comments because of the possibility of breaking such programs. Sure, though I don't think that application level code have to be dependent in logic on documentation string. The doc-string is just the _addition for debug_. No more, no less. It's when you use a new lib (my example with Redis's `get` method which should accept callback), you just get this help directly from here without going to some websites (which can even be down for this time) and solve the problems much faster. And for minified scripts, I think the option Remove doc-comments is the case. When designing language features, a designer always has some specific use cases in mind. But that doesn't restrict users of the language from discovering other use cases. Once a feature is incorporated into a language, implementation have to support all possible use cases, not just the original intended use case. That's why it is important for language designer to think broadly about all conceivable uses and feature interaction when extending a language. Sure, no application is required to have logic dependencies upon the content of a documentation string but once they exist any application could have such dependencies. As a language designers you have to think about the implications of such usages. It isn't good enough to just say that wasn't the intended use of the feature. Yes, of course it's true, we have to consider the most hardcore use-cases of our programs. Well, then I have to think on it, but the first thing which comes in mind -- already mentioned Remove doc-comments option for minifiers, i.e. a user himself is responsible for this action. Moreover, minification is again mostly for browser-scripting, where this help(...) functionality isn't so required as it is for the server programming in the console. And for the later case I wrote a simple version of such a pre-processor: https://gist.github.com/1186853 Simple example: /** * sum * @param {Number} x * @param {Number} y * The function of summation. */ function sum(x, y) { return x + y; } /** * multSum * @param {Number} x * @param {Number} y * @param {String} value * The function of calculation. */ function calculate(x, y, value) { // comment print(value + : + sum(x, y)); } // -- Test documentation -- // Result: // Help on sum function: // // /** // * sum // * @param {Number} x // * @param {Number} y // * The function of summation. // */ help(sum); // Help on calculate function: // // /** // * multSum // * @param {Number} x // * @param {Number} y // * @param {String} value // * The function of calculation. // */ help(calculate); // -- Test guards -- sum(1, 2); // 3, OK calculate(1, 2, value); // value: 3 sum(1, 2); // TypeError: y must be a number calculate(1, 2, 4); // TypeError: value must be a string Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: __doc__ for functions, classes, objects etc.
On 30.08.2011 19:33, Dean Landolt wrote: On Tue, Aug 30, 2011 at 10:41 AM, Dmitry A. Soshnikov dmitry.soshni...@gmail.com mailto:dmitry.soshni...@gmail.com wrote: On 30.08.2011 17:41, Rick Waldron wrote: On Tue, Aug 30, 2011 at 3:39 AM, Dmitry A. Soshnikov dmitry.soshni...@gmail.com mailto:dmitry.soshni...@gmail.com wrote: OK, let's up the topic. Seems there are no technical issues in the proposed thing -- we can simply either accept it or not. The question is whether it's needed and sound proposal and the feature to have in ECMAScript. Some summarized features below: + Ability to get help of any built-in and any user-defined function directly in runtime (in later case, authors should provide the documentations though) + Auto-suggest and hints of parameters and their types when typing function name in console. + Ability even to have sort of guards for types with issuing warnings in case if types mismatch (sort of recent contract.coffee projects and actually other langs, e.g. Haskell, Erlang, etc). - Code size will be increased to store the doc string. This can be optional in case of minimized scripts (lint tools can have option Remove doc-comments) As an example I show a spec description for `parseInt` function: 15.1.2.2 parseInt (string , radix) Let [[Documentation]] property of the `parseInt` function be the following string: The parseInt function produces an integer value dictated by interpretation of the contents of the string argument according to the specified radix. Leading white space in string is ignored. If radix is undefined or 0, it is assumed to be 10 except when the number begins with the character pairs 0x or 0X, in which case a radix of 16 is assumed. If radix is 16, number may also optionally begin with the character pairs 0x or 0X. ... x.x.xx help(F) A built-in, global object function property named help() will no doubt conflict with userland code It's derived question, we may choose any name which fits well (though, IMO `help` name isn't used much). That's tough to say for sure, and even if true still probably isn't good enough. Regardless, there's no excuse for this kind of global, especially in light of a module system. Sure, specifically in a repl you'd probably want to skip the require -- for this node offers up dot-prefixed repl keywords. So something like .help(F) would be a lot safer and nearly as convenience as a help global. Yes, I guess. Anyway, all this about only debug-in-console mode, so .help(...) would be just fine. I think it would be useful for the committee to weigh in on the idea of repl plugins. This particular design is pretty nice but it conflicts for statements beginning with non-zero-prefixed decimals. In practice I don't see this causing any real problems, but it'd be great if the grammer explicitly forbid this, effectively reserving it for repl hooks. Maybe, though, in contrast with other langs, ES is different since because of browser vendors has different implementations. Actually, there is no such implementation as ECMAScript. In contrast, languages such as e.g. Python or Erlang have the sample implementations (usually that which is placed directly on the website of the language), and there of course the attention to a good console and downloadable and installable in one click REPLs is paid much. And that's said, this increases and speeds up the learning of the language. I don't know what to propose in case of ECMAScript, since repeat, there is no such language as ECMAScript in real life and therefore, there is no the sample REPL for which it would be the best to have .help(...) function which shows the doc-comment of a function. And in case of a browser -- I don't think it's needed much. OTOH, of course devs. also debug the browser code in tools such as Firebug, where they also can use this .help(...). So I'm still thinking myself, is it worth to move it to the level of the ES spec (the [[Doc]] property and similar) or it's not needed much and is only for playing in console. OTOH, this playing in console is what makes Python the best in this respect. The main thing I want to clarify at this step, whether we need at all this thing in ES? Since committee keeps silence, I'd like to consider it better as Yes, we need it and there is nothing to add, rather than We don't need and don't want even to discuss (since there is no big sense in later, because the functionality seems useful). However, we need to clarify how *exactly* it's useful. Maybe using JS in console is so rare case and it isn't required much. OTOH, era of client-side-only-JS is behind and JS is also on server now
Re: __doc__ for functions, classes, objects etc.
On 30.08.2011 19:54, Rick Waldron wrote: On Tue, Aug 30, 2011 at 10:41 AM, Dmitry A. Soshnikov dmitry.soshni...@gmail.com mailto:dmitry.soshni...@gmail.com wrote: On 30.08.2011 17:41, Rick Waldron wrote: On Tue, Aug 30, 2011 at 3:39 AM, Dmitry A. Soshnikov dmitry.soshni...@gmail.com mailto:dmitry.soshni...@gmail.com wrote: OK, let's up the topic. Seems there are no technical issues in the proposed thing -- we can simply either accept it or not. The question is whether it's needed and sound proposal and the feature to have in ECMAScript. Some summarized features below: + Ability to get help of any built-in and any user-defined function directly in runtime (in later case, authors should provide the documentations though) + Auto-suggest and hints of parameters and their types when typing function name in console. + Ability even to have sort of guards for types with issuing warnings in case if types mismatch (sort of recent contract.coffee projects and actually other langs, e.g. Haskell, Erlang, etc). - Code size will be increased to store the doc string. This can be optional in case of minimized scripts (lint tools can have option Remove doc-comments) As an example I show a spec description for `parseInt` function: 15.1.2.2 parseInt (string , radix) Let [[Documentation]] property of the `parseInt` function be the following string: The parseInt function produces an integer value dictated by interpretation of the contents of the string argument according to the specified radix. Leading white space in string is ignored. If radix is undefined or 0, it is assumed to be 10 except when the number begins with the character pairs 0x or 0X, in which case a radix of 16 is assumed. If radix is 16, number may also optionally begin with the character pairs 0x or 0X. ... x.x.xx help(F) A built-in, global object function property named help() will no doubt conflict with userland code It's derived question, we may choose any name which fits well (though, IMO `help` name isn't used much). The main thing I want to clarify at this step, whether we need at all this thing in ES? I support this idea :) BTW, here are some incomplete numbers on help() (sort of) http://www.google.com/codesearch#search/q=lang:%5Ejavascript$%20help%5C(type=cs http://www.google.com/codesearch#search/q=lang:%5Ejavascript$%20help%5C%28type=cs OK, OK, you've convinced me ;) it's used much as I see. Though, would be the best name. Function.getDocumentation(...) is also nice but long. Funciton.getInfo(...) may return an object with meta-info: {documentation: ..., length: 2, arguments: {a: int, b: string}}. But don't wanna go down into the bikeshed. Dmitry. Since committee keeps silence, I'd like to consider it better as Yes, we need it and there is nothing to add, rather than We don't need and don't want even to discuss (since there is no big sense in later, because the functionality seems useful). However, we need to clarify how *exactly* it's useful. Maybe using JS in console is so rare case and it isn't required much. OTOH, era of client-side-only-JS is behind and JS is also on server now. And from this viewpoint, in the console, it's the best to get the help, hints for parameters and even type checking for functions. So, what should I do to apply the first meaning? Dmitry. When the `help` function is called on the F object, the following steps are taken: 1. If [[Class]] of the function is not Function throw TypeError 2. Let doc be [[Documentation]] property of F 2.1 If doc is `undefined` return empty string 2.2. return String(doc) It's a simplified version of course (moreover, Allen wanted to eliminate [[Class]], so -- it's just an example). Do we need this? Dmitry. On 09.08.2011 23:59, Dmitry A. Soshnikov wrote: On 23.08.2011 20:54, Brendan Eich wrote: A convenient notation for multiline documentation comments, with convenient reflection (*not* via toString() scraping!), would be a fine thing. Yes, exactly this -- help(...) function, and also good auto-complete of object methods helped me some time ago formerly to learn Python very quickly just playing with it in console. By the way, ECMAScript (who will take responsibility to implement the ECMAScript -- ethanol implementation? :)) also needs some installation binaries with the console. And yes -- with this great features for learning -- auto-complete of methods (the best thing
Re: __doc__ for functions, classes, objects etc.
Right. And this is where Python just wins. In respect of bult-ins and methods provided by framework authors. That's said in the initial letter, we can always go to the language documentation website and read it, but to the help in-place seems much better. Though, there is another issue here (beside the source- and byte- code size increasing). The offline documentation embedded inside the function objects may become obsolete, while the online is up-to-date. But, for the specified built-ins it's not the case, since the spec doesn't change too often. And regarding user-defined framework codes, anyway the code is parsed each time -- it is the property and the deal of the JS engine to correctly parse doc-comment and assign it as a property to a function. That is, the documentation may change in-time and if you use external script file, then you always have up-to-date documentation. Dmitry. On 30.08.2011 20:09, Dave Fugate wrote: This feature is particularly useful for /framework/ authors and their users. Countless times I've found myself using a browser's console debugging tool to figure out why something's busted. In these cases, I nearly always resort to navigating to some JS framework's website for their documentation or scrutinizing their code directly to figure out what's going wrong. If I could just call 'printHelp(xyzsomeMethod)', less of my time would be used. The other bit of utility here is that framework documentation can live side-by-side with the code and be automatically generated from it (e.g., http://pydoc.org/2.5.1/timeit.html) as opposed to maintaining it separately. A very useful feature to have from my Python-biased perspectiveJ My best, Dave *From:*es-discuss-boun...@mozilla.org [mailto:es-discuss-boun...@mozilla.org] *On Behalf Of *Dmitry A. Soshnikov *Sent:* Tuesday, August 30, 2011 7:42 AM *To:* Rick Waldron *Cc:* Brendan Eich; es-discuss Steen *Subject:* Re: __doc__ for functions, classes, objects etc. On 30.08.2011 17:41, Rick Waldron wrote: On Tue, Aug 30, 2011 at 3:39 AM, Dmitry A. Soshnikov dmitry.soshni...@gmail.com mailto:dmitry.soshni...@gmail.com wrote: OK, let's up the topic. Seems there are no technical issues in the proposed thing -- we can simply either accept it or not. The question is whether it's needed and sound proposal and the feature to have in ECMAScript. Some summarized features below: + Ability to get help of any built-in and any user-defined function directly in runtime (in later case, authors should provide the documentations though) + Auto-suggest and hints of parameters and their types when typing function name in console. + Ability even to have sort of guards for types with issuing warnings in case if types mismatch (sort of recent contract.coffee projects and actually other langs, e.g. Haskell, Erlang, etc). - Code size will be increased to store the doc string. This can be optional in case of minimized scripts (lint tools can have option Remove doc-comments) As an example I show a spec description for `parseInt` function: 15.1.2.2 parseInt (string , radix) Let [[Documentation]] property of the `parseInt` function be the following string: The parseInt function produces an integer value dictated by interpretation of the contents of the string argument according to the specified radix. Leading white space in string is ignored. If radix is undefined or 0, it is assumed to be 10 except when the number begins with the character pairs 0x or 0X, in which case a radix of 16 is assumed. If radix is 16, number may also optionally begin with the character pairs 0x or 0X. ... x.x.xx help(F) A built-in, global object function property named help() will no doubt conflict with userland code It's derived question, we may choose any name which fits well (though, IMO `help` name isn't used much). The main thing I want to clarify at this step, whether we need at all this thing in ES? Since committee keeps silence, I'd like to consider it better as Yes, we need it and there is nothing to add, rather than We don't need and don't want even to discuss (since there is no big sense in later, because the functionality seems useful). However, we need to clarify how *exactly* it's useful. Maybe using JS in console is so rare case and it isn't required much. OTOH, era of client-side-only-JS is behind and JS is also on server now. And from this viewpoint, in the console, it's the best to get the help, hints for parameters and even type checking for functions. So, what should I do to apply the first meaning? Dmitry. When the `help` function is called on the F object, the following steps are taken: 1. If [[Class]] of the function is not Function throw TypeError 2. Let doc be [[Documentation]] property of F 2.1 If doc is `undefined` return empty string 2.2. return String(doc) It's a simplified version of course (moreover, Allen wanted to eliminate
Re: __doc__ for functions, classes, objects etc.
On 30.08.2011 20:39, Allen Wirfs-Brock wrote: On Aug 30, 2011, at 12:39 AM, Dmitry A. Soshnikov wrote: OK, let's up the topic. Seems there are no technical issues in the proposed thing -- we can simply either accept it or not. The question is whether it's needed and sound proposal and the feature to have in ECMAScript. There certainly are technical issues. To start, by making this part of the core language you would be defining a feature that can be used by any application code. For example, a program might choose to encode essential runtime metadata as its documentation. Because of that possibility, the [[Documentation]] information must always be available at runtime. Minimizers or obfuscators could not remote documentation comments because of the possibility of breaking such programs. Sure, though I don't think that application level code have to be dependent in logic on documentation string. The doc-string is just the _addition for debug_. No more, no less. It's when you use a new lib (my example with Redis's `get` method which should accept callback), you just get this help directly from here without going to some websites (which can even be down for this time) and solve the problems much faster. And for minified scripts, I think the option Remove doc-comments is the case. Rather than trying to extend the core language, I suggest that this type of functionality is better viewed as simply another form of reflection that would be best modeled as a kind of Mirror. It should manifest it self as a module that provides access to such mirrors. For example, you might access it as var docMirrorFn = DocMirror.for(fn); var helpStr = docMirrorFn.help(); var helpStrLocalized = docMirrorFn.helpLocale(); var helpStrI18N = docMirrorFn.helpLocale(someLocale); var competeDoc = docMirrorFn.full({format: 'HTML'}); var src = docMirrorFn.sourceCode; // etc. Yeah, why not. Also is a variant. Though, for the end-user I'd like to see all this stuff encapsulated somewhere and to get the needed thing as just .help(...). But, yes, it can be done by a host-environment as a debugger which provides this .help(...) which inside does this long manipulations. If a REPL provider wants to offer a help command it would implement it by accessing an appropriate documentation mirror. Yes. The definition of the DocMirror module would define how the appropriate meta data is obtained and even alternatives and fall backs for obtaining it that does not require direct embedding in the loaded JS code. My recommendation would be rather than trying to extend to the core language at this time, experiment with defining such a module. At some point we may be ready to consider standardizing such modules but even before that there is nothing preventing community adoption of such a convention. Yes, it's not a problem to write a pre-processor of doc-comments (actually we have many auto-doc generation tools for JavaDocs), i.e.: to turn: /** * connect * @param {String} host * @param {Number} port * Connects to my awesome host */ function connect(host, port) { ... } into the: function connect(host, port) { ... } connect.__doc__ = connect\n@param {String} host\n@param {Number} port\nConnects to my awesome host or even into the: function connect(host, port) { // ! pre-processor header !! if (typeof host != string) console.warning(connect: host must be a string); if (typeof port != number) console.warning(connect: port must be a number); // ! end of pre-processor header !! // rest of user-defined implementation } it's just a variant of course (we need not to show this embedded checker in the `toString` decompilation of a function and to handle prologue before for directives), but the general idea is this. It's not the problem to write such a pre-processor, but pre-processor means to do something additional manually by hands before the execution and not all users use some building-tools for that. OTOH, we can write an extension for e.g. Narcissus to handle it on the engine's level and try will it go or not (but something suggests me that it will ;)). Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: __doc__ for functions, classes, objects etc.
OK, let's up the topic. Seems there are no technical issues in the proposed thing -- we can simply either accept it or not. The question is whether it's needed and sound proposal and the feature to have in ECMAScript. Some summarized features below: + Ability to get help of any built-in and any user-defined function directly in runtime (in later case, authors should provide the documentations though) + Auto-suggest and hints of parameters and their types when typing function name in console. + Ability even to have sort of guards for types with issuing warnings in case if types mismatch (sort of recent contract.coffee projects and actually other langs, e.g. Haskell, Erlang, etc). - Code size will be increased to store the doc string. This can be optional in case of minimized scripts (lint tools can have option Remove doc-comments) As an example I show a spec description for `parseInt` function: 15.1.2.2 parseInt (string , radix) Let [[Documentation]] property of the `parseInt` function be the following string: The parseInt function produces an integer value dictated by interpretation of the contents of the string argument according to the specified radix. Leading white space in string is ignored. If radix is undefined or 0, it is assumed to be 10 except when the number begins with the character pairs 0x or 0X, in which case a radix of 16 is assumed. If radix is 16, number may also optionally begin with the character pairs 0x or 0X. ... x.x.xx help(F) When the `help` function is called on the F object, the following steps are taken: 1. If [[Class]] of the function is not Function throw TypeError 2. Let doc be [[Documentation]] property of F 2.1 If doc is `undefined` return empty string 2.2. return String(doc) It's a simplified version of course (moreover, Allen wanted to eliminate [[Class]], so -- it's just an example). Do we need this? Dmitry. On 09.08.2011 23:59, Dmitry A. Soshnikov wrote: On 23.08.2011 20:54, Brendan Eich wrote: A convenient notation for multiline documentation comments, with convenient reflection (*not* via toString() scraping!), would be a fine thing. Yes, exactly this -- help(...) function, and also good auto-complete of object methods helped me some time ago formerly to learn Python very quickly just playing with it in console. By the way, ECMAScript (who will take responsibility to implement the ECMAScript -- ethanol implementation? :)) also needs some installation binaries with the console. And yes -- with this great features for learning -- auto-complete of methods (the best thing to investigate objects just pressing `tab`) and help(...) function. I remember ES4 had/has the REPL, why not ES5? Of course we have all those consoles directly from the browsers (and also Node.js REPL), but it could be useful. Anyway, it's another topic, just relatively touches help(...) functions. Some of the design dimensions: 0. Comment vs. string / quasiliteral? 1. function-only, or object literal too -- or any declaration? I think functions are the main case, yes. Not sure about literals, since there are open issues such as, how to document a property (via descriptor field?)? 2. Before function, a la javadoc comments, or first thing in body, a la the prologue directive idea? That's said, if before, then we should consider white-spaces and newlines after the comment and before the function header (though, as well as in the prologue). If before, then tones of old code written in javadoc will just work with the new engine. OTOH, this means that the exact syntax of javadocs will be standardized at the level of the spec (and it's a sound thing -- people will have to write exactly e.g. @property that the doc-er catch it correctly. OTOH again -- why not? -- to standardize common syntax of documenting functions). However, the spec may not parse the exact content of the comment but just save it as a string, regardless of what is written insides. A variant with inside is also good, underlines that the comment is sort of a function's property (I like yours simple doc name for that). Both variants are good, just outside has the advantage that the old code will just hook on it. 3. Reflected via function .doc property, a Function.extractDocComment static method, or something even more mirror-like/stratified? Yes, both are fine, .doc is great. Perhaps, even global binding help(...). I'm not sure what is best, I lack experience programming in languages with doc-comment or triple-quoted equivalents (Python attached tests, e.g.). Comments (heh) welcome. Thinking about 1, I would start with function-only. Yes, this is the main case. For 2 I'm inclined to say in body because it's too easy to lose the before context during the life of a function, compared to losing part of the body by accident. At first glance there should be no issues with parsing in both cases. We sure have to restrict that only
Re: An news on block lambda versus arrow function syntax?
On 30.08.2011 18:22, Axel Rauschmayer wrote: Is there a consensus building in TC39 for one or the other? Will any of them make it into ES.next? What I like about block lambdas is that one will automatically use lexical this where necessary. Just yesterday, dynamic this versus lexical this bit me again. Fat arrows IIRC also bind `this` lexically. The main thing of blocks is TCP where we can exit from passed closures to the outside, but not to the caller. Personally, I also like both: and arrows and blocks :) Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Object.methods
On 24.08.2011 3:07, Allen Wirfs-Brock wrote: On Aug 9, 2011, at 2:05 PM, Dmitry A. Soshnikov wrote: On 24.08.2011 0:39, Allen Wirfs-Brock wrote: I'm don't really see the that they are needed enough to build these in when they can be synthesized pretty easily. What is the justification for these and not others such as getAccessorProperties, getDataProperties, getNonWritableProperties, etc. Maybe, why not? `Object.methods` is just standard in some languages (e.g. Ruby, `foo.instance_methods`). Yes, all of yours listed above could be either built-in or self-implemented, don't know how often they are needed IRL. This topic follows the recent near topic with doc-comments of functions. The same, playing with a new language in console it's the best just to type e.g. `foo.methods` (like in Ruby) and to see directly the list of methods to which the object responds. Besides, perhaps they can be used in other meta-level programming, but the initial idea seems studying the language in the console and playing with objects (not sure though whether it's a sound reason to be accepted for standardization). Dmitry. One difference between Ruby and JavaScript is that Ruby has a formal concept of method and JavaScript does not. (JFTR, moreover, Ruby has _only_ methods in this cases, that is, accessors for private instance vars, but anyway it doesn't matter much) I propose to use definition of a method as a property which value is a function. That's after all, is the same as from ES5 spec: ECMA-262-5: 4.3.27 method function that is the value of a property. Whether a JS data property whose value is a function is considered to be a method or function valued instance variable is highly situational. For the simplicity and because instances themselves can store methods and override them from parent's prototypes, I think the simplest version is again description from 4.3.27. Similarly, I can also imagine an interpretation that only inherited function valued data properties are considered to be methods or that methods need to be non-writable and non-enumerable. No, no, it's not required IMO. Because of dynamics, instances may have own methods -- why not? And they are still methods, that is some action which is _activated_ and has `this` as the instance. Adding super bindings also complicates things. Perhaps, only properties with function values that have super bindings to the object or one of its prototypes should be considered a method. Which of these definitions should be use for a built-in Object.methods. Object.getMethods(object) - var methods = {}; do { for (var [propertyName, value] in items(Object.getOwnPropertyNames(object)) if (typeof value == function) { methods[propertyName] = value; } } while (object = Object.getPrototypeOf(object)); return methods; Objects.getMethods(foo).createBar.doc // shows description of createBar function on foo object. Don't know. Just one-of possible ways. E.g. it may consider only own methods. I'm all for rich interactive environments for working with JavaScript and such environments do need to access or infer metadata about JavaScript code. Absolutely. Currently ES doesn't even have a _good console_ to try the language. Once again, these two things as: (1) good auto-complete of property names which is shown by pressing `tab` after dot property accessor, and (2) the ability to get help information on the function directly from the console -- help(parseInt) - Converts a string into a num... makes learning the language much quicker and fun. I think you should think on implementing the sample version of ES -- the ES itself and to spread it as downloadable binaries from the ecmascript.org. Then people will just be able (1) to run it and pay in the console learning the methods and properties of object, getting the documentation right from here and (2) to attach the engine to favorite editor and call it right from the editor by just pressing F5 and getting output to the editors console back. There's no need to install Firefox or Chrome first, go to their consoles, write there with inconvenient way (or to copy-paste code from convenient editor to the inconvenient Firebug's console and run). Because now, to compile e.g. SpiderMonkey, it is required long process with installing Mozilla-build, then to install many patches to VS (because my 2005 compiler isn't supported anymore), etc. It doesn't matter much of course, I can handle it. But it would be the best if newcomers could just download ECMAScript (for Windows, Mac, Linux) and just execute it. And already in the console to play with it and to get the help directly and introspect meta-information, such as methods, etc. Python did it. It's learned in a week max. Why not ES? However, I don't necessarily think the a REPL model is the best exemplar for such an environment. Maybe, don't know. But the internal information on functions
Triple-strings
Hi again, And another topic which I'd like to separate from the doc-comments topic is the triple-strings. The rationale is not to escape the double/single quotes when describing something bigger than one line (usually these are comments, but other simple strings with many of double quotes are also the case). var description = This is \ECMAScipt\, \The language of the 'Web' \ . vs. var description = ' This is ECMAScript, The language of the \'Web\' ' vs. var description = This is ECMAScript, The language of the 'Web' It also may continue to new lines without escaping and concatenation: This is \ECMAScipt\,\ + \The language of the 'Web' \ . vs. This is ECMAScript, The language of the 'Web' ? Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Triple-strings
On 24.08.2011 20:19, Brendan Eich wrote: On Aug 24, 2011, at 2:44 AM, Dmitry A. Soshnikov wrote: Hi again, And another topic which I'd like to separate from the doc-comments topic is the triple-strings. The rationale is not to escape the double/single quotes when describing something bigger than one line (usually these are comments, but other simple strings with many of double quotes are also the case). We had a triple-quoted string proposal for ES4. That was long ago. http://wiki.ecmascript.org/doku.php?id=proposals:triple_quotes Ah, didn't know, thanks. The answer now is quasi-literals: http://wiki.ecmascript.org/doku.php?id=harmony:quasis Yes, I'm aware about `quasis`, but seems inattentively considered all the cases. No need to stutter three times -- just use `. Did you miss this one? Yes, definitely. Thanks for mention. OK, then the topic with is obsolete. Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: __doc__ for functions, classes, objects etc.
So, is that's all? Anyone else thinks it's a needed thing in the ES? On 22.08.2011 14:57, Dmitry A. Soshnikov wrote: On 22.08.2011 12:47, Irakli Gozalishvili wrote: I'm very much interested in getting something like this! In fact I have been useing similar documentation style for some time already: function doc(lambda) { var doc = /\/\*([\s\S]*)?\*\//.exec(String(lambda)) return doc ? doc[1].trim() : '' } function sum(a, b) { /* Calculates sum of given `a` and `b` arguments */ return a + b; } doc(sum) \\ Calculates sum of given `a` and `b` arguments Unfortunately this does not works on spidermonkey based js engines :( Right. That's why I raised this issue, because the functionality is very powerful. Backing to my concrete example with redis, I just wanted to understand why the heck client.get('x'), after setting client.set('x', 10) returns for me `true`, but not 10. If I had this help(...) functionality I'd be able to get the description right from the console, saying that `.get` function should accept callback which already returns the value: client.get('x', function(err, data) {return data;}) - 10. I of course could go to the documentation website (what actually I did after my fail tries :)), but I think it goes without saying that it would be the best if I could do this right from the console! Besides, this [[Documentation]] property can be used in hints (with showing parameters and their types) when typing function name. From this viewpoint Python just wins and IMO we should have this feature in the ES. Also I found that best way to support this on spidermonkey is via E4X hacks function sum(a, b) { docCalculates sum of given `a` and `b` arguments/doc return a + b } Unfortunately I don't have any solution working across all engines that would not require multiline string escaping: function sum(a, b) { var doc = Calculates \ sum of given\ `a` and `b` argumnets return a + b } Yes, it's another pros to have [[Documentation]] standardized. On Sunday, 2011-08-07 at 21:30 , Dmitry A. Soshnikov wrote: On 21.08.2011 22:26, Peter van der Zee wrote: On Sun, Aug 7, 2011 at 6:56 PM, Dmitry A. Soshnikov dmitry.soshni...@gmail.com mailto:dmitry.soshni...@gmail.com wrote: Hi, What about to standardize (Python's) __doc__-umentation comments for JS? What's the difference between that and the /** ... */ way of JSDoc? /** * This function does stuff * @constructor * @param {Object} foo * @returns {Array} */ var f = function(){ ... }; It doesn't matter for me how *exactly* (syntactically) it will look like. In this particular case the comment is outside a function's body -- you then should consider and allow or not newlines after the doc-comment, etc. Though, as well as in case of placing the comment inside the body, but in this case I think we should mention that the doc-comment is should be placed in the prologue. What would a new language construct for this solve? That's said, triple-strings by themselves (not only for doc-comments) are very powerful construct to have and standardize. Did you work with them in Python or CoffeeScript? P.S.: Another thing to notice. As was mentioned, it's good to have this ability also for simple objects. From this viewpoint doc-string should be set via property. But if I remember correctly, someone (all?) from the committee didn't like Python's __names__ (despite the fact that JS actually use them for __proto__, __noSuchMethod__, __count__, __parent__, __iterator__ etc. -- non is standardized, stratified meta-level won). But it would be great to have the ability to: let foo = { __doc__: My awesome object, x: 100, y: 200 }; Object.help(foo); // My awesome object or simply `help(foo)`. I don't think we need special property for that, as anyone can just use `doc` or whatever they decide, bigger issue IMO is a property docs. How do you document `foo.x` if x is not a function or object ? It was just an example. Mostly this doc is needed for functions. Though, we can think how we can do this for every property. Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: __doc__ for functions, classes, objects etc.
On 23.08.2011 20:54, Brendan Eich wrote: A convenient notation for multiline documentation comments, with convenient reflection (*not* via toString() scraping!), would be a fine thing. Yes, exactly this -- help(...) function, and also good auto-complete of object methods helped me some time ago formerly to learn Python very quickly just playing with it in console. By the way, ECMAScript (who will take responsibility to implement the ECMAScript -- ethanol implementation? :)) also needs some installation binaries with the console. And yes -- with this great features for learning -- auto-complete of methods (the best thing to investigate objects just pressing `tab`) and help(...) function. I remember ES4 had/has the REPL, why not ES5? Of course we have all those consoles directly from the browsers (and also Node.js REPL), but it could be useful. Anyway, it's another topic, just relatively touches help(...) functions. Some of the design dimensions: 0. Comment vs. string / quasiliteral? 1. function-only, or object literal too -- or any declaration? I think functions are the main case, yes. Not sure about literals, since there are open issues such as, how to document a property (via descriptor field?)? 2. Before function, a la javadoc comments, or first thing in body, a la the prologue directive idea? That's said, if before, then we should consider white-spaces and newlines after the comment and before the function header (though, as well as in the prologue). If before, then tones of old code written in javadoc will just work with the new engine. OTOH, this means that the exact syntax of javadocs will be standardized at the level of the spec (and it's a sound thing -- people will have to write exactly e.g. @property that the doc-er catch it correctly. OTOH again -- why not? -- to standardize common syntax of documenting functions). However, the spec may not parse the exact content of the comment but just save it as a string, regardless of what is written insides. A variant with inside is also good, underlines that the comment is sort of a function's property (I like yours simple doc name for that). Both variants are good, just outside has the advantage that the old code will just hook on it. 3. Reflected via function .doc property, a Function.extractDocComment static method, or something even more mirror-like/stratified? Yes, both are fine, .doc is great. Perhaps, even global binding help(...). I'm not sure what is best, I lack experience programming in languages with doc-comment or triple-quoted equivalents (Python attached tests, e.g.). Comments (heh) welcome. Thinking about 1, I would start with function-only. Yes, this is the main case. For 2 I'm inclined to say in body because it's too easy to lose the before context during the life of a function, compared to losing part of the body by accident. At first glance there should be no issues with parsing in both cases. We sure have to restrict that only the first multiline comment from _above_ of a function is treated as doc-comment. It will not touch any other upper-comments // this one isn't caught /* and this one also */ /** * but this is OK */ function foo() {} console.log(foo.doc); // but this is OK With the prologue -- there also directives' places should be considered. I think the best place for them is under the doc-comment. function foo() { My function use strict; } Regarding 3, I bet Function.extractDocComment or a better name wins, especially if the whole solution allows monkey-patching a polyfill for downrev browsers that support source recovery (not SpiderMonkey's decompiler). Yes, maybe. Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Object.methods
On 23.08.2011 21:32, Allen Wirfs-Brock wrote: The rough convention we were following for ES5 was that Object.* functions that were expected to be used in application layer code had short imperative names like keys, create, freeze, etc. Functions that were expected to be primarily used in meta layers of framework or other reflective purposes have long descriptive names. I see, thanks for clarifications Allen, it makes sense. Though... the consistency also matters ;) The wordiness of the names is largely a function of the degrees of variation that might be consider. For example, own vs. all properties or property names vs property descriptors. getOwnPropertyDescriptor/getOwnPropertyNames are the winners in that category. defineProperty/defineProperties don't need the own because properties are always defined on a specific object and don't need descriptor because there are no similar operations that don't use descriptors. Yes. And what about this method Object.getMethods(...), Object.getMethodNames(...). Do we need it? I think it can be useful (since methods can be non-enumerable, and Object.keys(...) won't help, and after Object.getOwnPropertyNames(...) you have to manually filter them when `typeof` is function) Dmitry. On Aug 7, 2011, at 12:36 PM, Dmitry A. Soshnikov wrote: Hi again, I'm about to propose `Object.methods(obj)` meta-method (or `Object.getMethods(obj)`). Unfortunately naming convention is inconsistent (arrgh!) -- `Object.keys` (hello, Ruby and Prototype.js) vs. Object.getOwnPropertyNames (o_O hello Java), so the method name can be chosen later. But the idea is to get the properties (or their names) which are methods on the object. Proposed: var foo = { bar: function () {}, __proto__: {baz: function () {}} }; - Object.getMethods(foo) - {bar: function () {}, baz: function () {}} - Object.getOwnMethod(foo) - {bar: function () {}} - Object.getMethodNames(foo) - [bar, baz] - Object.getOwnMethodNames(foo) - [bar] Of course it can be easily implemented in JS itself just filtering the Object.getMySummerVacationWasLongOwnPropertyNames or Object.keys(...), but directly in the engine it will be more efficient. Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Object.methods
On 24.08.2011 0:39, Allen Wirfs-Brock wrote: On Aug 9, 2011, at 1:03 PM, Dmitry A. Soshnikov wrote: And what about this method Object.getMethods(...), Object.getMethodNames(...). Do we need it? I think it can be useful (since methods can be non-enumerable, and Object.keys(...) won't help, and after Object.getOwnPropertyNames(...) you have to manually filter them when `typeof` is function) I'm don't really see the that they are needed enough to build these in when they can be synthesized pretty easily. What is the justification for these and not others such as getAccessorProperties, getDataProperties, getNonWritableProperties, etc. Maybe, why not? `Object.methods` is just standard in some languages (e.g. Ruby, `foo.instance_methods`). Yes, all of yours listed above could be either built-in or self-implemented, don't know how often they are needed IRL. This topic follows the recent near topic with doc-comments of functions. The same, playing with a new language in console it's the best just to type e.g. `foo.methods` (like in Ruby) and to see directly the list of methods to which the object responds. Besides, perhaps they can be used in other meta-level programming, but the initial idea seems studying the language in the console and playing with objects (not sure though whether it's a sound reason to be accepted for standardization). Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: __doc__ for functions, classes, objects etc.
On 22.08.2011 12:47, Irakli Gozalishvili wrote: I'm very much interested in getting something like this! In fact I have been useing similar documentation style for some time already: function doc(lambda) { var doc = /\/\*([\s\S]*)?\*\//.exec(String(lambda)) return doc ? doc[1].trim() : '' } function sum(a, b) { /* Calculates sum of given `a` and `b` arguments */ return a + b; } doc(sum) \\ Calculates sum of given `a` and `b` arguments Unfortunately this does not works on spidermonkey based js engines :( Right. That's why I raised this issue, because the functionality is very powerful. Backing to my concrete example with redis, I just wanted to understand why the heck client.get('x'), after setting client.set('x', 10) returns for me `true`, but not 10. If I had this help(...) functionality I'd be able to get the description right from the console, saying that `.get` function should accept callback which already returns the value: client.get('x', function(err, data) {return data;}) - 10. I of course could go to the documentation website (what actually I did after my fail tries :)), but I think it goes without saying that it would be the best if I could do this right from the console! Besides, this [[Documentation]] property can be used in hints (with showing parameters and their types) when typing function name. From this viewpoint Python just wins and IMO we should have this feature in the ES. Also I found that best way to support this on spidermonkey is via E4X hacks function sum(a, b) { docCalculates sum of given `a` and `b` arguments/doc return a + b } Unfortunately I don't have any solution working across all engines that would not require multiline string escaping: function sum(a, b) { var doc = Calculates \ sum of given\ `a` and `b` argumnets return a + b } Yes, it's another pros to have [[Documentation]] standardized. On Sunday, 2011-08-07 at 21:30 , Dmitry A. Soshnikov wrote: On 21.08.2011 22:26, Peter van der Zee wrote: On Sun, Aug 7, 2011 at 6:56 PM, Dmitry A. Soshnikov dmitry.soshni...@gmail.com mailto:dmitry.soshni...@gmail.com wrote: Hi, What about to standardize (Python's) __doc__-umentation comments for JS? What's the difference between that and the /** ... */ way of JSDoc? /** * This function does stuff * @constructor * @param {Object} foo * @returns {Array} */ var f = function(){ ... }; It doesn't matter for me how *exactly* (syntactically) it will look like. In this particular case the comment is outside a function's body -- you then should consider and allow or not newlines after the doc-comment, etc. Though, as well as in case of placing the comment inside the body, but in this case I think we should mention that the doc-comment is should be placed in the prologue. What would a new language construct for this solve? That's said, triple-strings by themselves (not only for doc-comments) are very powerful construct to have and standardize. Did you work with them in Python or CoffeeScript? P.S.: Another thing to notice. As was mentioned, it's good to have this ability also for simple objects. From this viewpoint doc-string should be set via property. But if I remember correctly, someone (all?) from the committee didn't like Python's __names__ (despite the fact that JS actually use them for __proto__, __noSuchMethod__, __count__, __parent__, __iterator__ etc. -- non is standardized, stratified meta-level won). But it would be great to have the ability to: let foo = { __doc__: My awesome object, x: 100, y: 200 }; Object.help(foo); // My awesome object or simply `help(foo)`. I don't think we need special property for that, as anyone can just use `doc` or whatever they decide, bigger issue IMO is a property docs. How do you document `foo.x` if x is not a function or object ? It was just an example. Mostly this doc is needed for functions. Though, we can think how we can do this for every property. Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
__doc__ for functions, classes, objects etc.
Hi, What about to standardize (Python's) __doc__-umentation comments for JS? Not exactly in this name with underscores, but the idea itself. I remember recent discussion on Twitter where Brendan proposed to use a prologue string for that: function foo() { this is the super function } then having some util which can analyze string decompilation of the function shows the documentation: Object.getDocumentation(foo) - this is the super function. However, engines usually optimize this case and remove dead-code. Moreover, `toString` for functions is not standardized also. So all these are just toys and examples. In contrast -- Python's __doc__ make this documentation as a property of function. It can be some internal property -- no matter, for that Object.getDoc(fn) will read this [[Documentation]] stuff. Why did I recall it? -- a real practical case -- just installed redis k-w database to play and wanted to see the documentation right from the node's console -- but... can't. There's no such an ability in JavaScript -- which is the best in Python. So if to accept triple-string and comments we catch two things at once (after all, triple-strings are useful by themselves): function foo() { Still the stuff is super. @author Me And double quotes are not needed to escape, as well as 'single' // implementation } Object.getDoc(foo) - Still the stuff is super.\n@author MeAnd double \quotes\ are not needed to escape,\nas well as 'single' Huh? Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: __doc__ for functions, classes, objects etc.
On 21.08.2011 22:26, Peter van der Zee wrote: On Sun, Aug 7, 2011 at 6:56 PM, Dmitry A. Soshnikov dmitry.soshni...@gmail.com wrote: Hi, What about to standardize (Python's) __doc__-umentation comments for JS? What's the difference between that and the /** ... */ way of JSDoc? /** * This function does stuff * @constructor * @param {Object} foo * @returns {Array} */ var f = function(){ ... }; It doesn't matter for me how *exactly* (syntactically) it will look like. In this particular case the comment is outside a function's body -- you then should consider and allow or not newlines after the doc-comment, etc. Though, as well as in case of placing the comment inside the body, but in this case I think we should mention that the doc-comment is should be placed in the prologue. What would a new language construct for this solve? That's said, triple-strings by themselves (not only for doc-comments) are very powerful construct to have and standardize. Did you work with them in Python or CoffeeScript? P.S.: Another thing to notice. As was mentioned, it's good to have this ability also for simple objects. From this viewpoint doc-string should be set via property. But if I remember correctly, someone (all?) from the committee didn't like Python's __names__ (despite the fact that JS actually use them for __proto__, __noSuchMethod__, __count__, __parent__, __iterator__ etc. -- non is standardized, stratified meta-level won). But it would be great to have the ability to: let foo = { __doc__: My awesome object, x: 100, y: 200 }; Object.help(foo); // My awesome object or simply `help(foo)`. Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Object.methods
Hi again, I'm about to propose `Object.methods(obj)` meta-method (or `Object.getMethods(obj)`). Unfortunately naming convention is inconsistent (arrgh!) -- `Object.keys` (hello, Ruby and Prototype.js) vs. Object.getOwnPropertyNames (o_O hello Java), so the method name can be chosen later. But the idea is to get the properties (or their names) which are methods on the object. Proposed: var foo = { bar: function () {}, __proto__: {baz: function () {}} }; - Object.getMethods(foo) - {bar: function () {}, baz: function () {}} - Object.getOwnMethod(foo) - {bar: function () {}} - Object.getMethodNames(foo) - [bar, baz] - Object.getOwnMethodNames(foo) - [bar] Of course it can be easily implemented in JS itself just filtering the Object.getMySummerVacationWasLongOwnPropertyNames or Object.keys(...), but directly in the engine it will be more efficient. Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Where in spec does it explain why setting the value of an existing property will change its [[Enumerable]] attribute.
It shouldn't, even in ES3 (read attentively). Dmitry. On 17.08.2011 8:44, John-David Dalton wrote: So @kitcambridge and I were talking spec and started trying to find in spec something that explains why something like: Array.prototype.reduce which is by default { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true } will change to [[Enumerable]]: true when: Array.prototype.reduce = function() {…}; So far we have struck out. In ES3 we found 8.6.2.2 [[Put]](P, V) http://bclary.com/2004/11/07/#a-8.6.2.2 and its step 4: 4. Set the value of the property to V. The attributes of the property are not changed. And then we dug into ES5.1 and its [[Put]] http://es5.github.com/#x8.12.5 and its step step 3a which leads to [[DefineOwnProperty]] with a Desc of {[[Value]]: V} and its step 10b to 12, then 13. but couldn't find where it stated changing the [[Enumerable]] attribute. Would you all help point to where this is defined in spec? Thanks, JDD ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Function#bind [[HasInstance]] question.
Once again (if the Twitter's discussion doesn't satisfy you): Quick overview: https://gist.github.com/1149186 Detailed overview: http://dmitrysoshnikov.com/notes/note-1-ecmascript-bound-functions/ So the Firefox is correct saying `true`. Dmitry. On 16.08.2011 18:26, John-David Dalton wrote: Sorry about the last empty reply, GMail got ahead of itself :D So Chrome and Firefox disagree on their Function#bind implementation. http://es5.github.com/#x15.3.4.5.2 http://es5.github.com/#x15.3.4.5.3 ~~~ js function Bar() { return 1; } var bound = Bar.bind({}); new bound instanceof bound; // Firefox reports `true`, Chrome `false` (I think Chrome is right) new bound instance of Bar; // Firefox and Chrome report `true` ~~~ The test262 doesn't appear to cover this case. What is the correct result of `new bound instance of bound;` and why? -JDD ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Shim for ES.next code?
There are many already I guess, e.g. pair of possible ES6 methods https://github.com/DmitrySoshnikov/es-laboratory/blob/master/src/es6.js, and also from any other framework (such as String.repeat). What's the goal? None of discussed methods is standardized yet. But, if you think currently needed, just start to collect and implement them. You will implement just a library. Possibly users will start to use this library (exactly yours library, but not another form tones of), and then it can turn out that ES will standardize another behavior for the same method, which will mean break the web. There will be two ways -- either to standardize yours as de-facto standard (if it will be widely spread), or users of your shim will have to correct old code. However, if some of methods are already 100% in the ES.next and their behavior is 100% accepted (in what I have doubts), then, yes, of course do it -- it will be good to have it collected. Dmitry. On 31.07.2011 18:33, Axel Rauschmayer wrote: Is anyone planning to collect the planned utility methods (Array.from(), String.repeat(), Object.getOwnProperties(), etc.) in a single file where each of the methods is conditionally added to the appropriate objects. If not, I would do so and publish the result on GitHub. Compare: ECMAScript 5 shim. https://github.com/kriskowal/es5-shim/ Greetings, Axel ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Term “data property” – ambiguous?
On 21.07.2011 19:10, Axel Rauschmayer wrote: Function-valued data properties = methods Non-function-valued data properties = ? Just properties. A method is just a `sounding sugar` for function-valued properties in this case. Dmitry. [[[Sent from a mobile device. Please forgive brevity and typos.]]] Dr. Axel Rauschmayer a...@rauschma.de Home: http://rauschma.de Blog: http://2ality.com On 21.07.2011, at 16:54, Brendan Eichbren...@mozilla.com wrote: On Jul 21, 2011, at 3:09 AM, Axel Rauschmayer wrote: Compare: (1) named data property versus named accessor property versus internal property. (2) data property versus method Thus, “data property” seems to be ambiguous. ECMA-262 is not ambiguous. A method is a data property. Pretending otherwise (see ECMA-357) is folly. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: An extend operator is a natural companion to |
On 19.07.2011 20:59, Brendan Eich wrote: On Jul 19, 2011, at 7:39 AM, Sean Eagan wrote: On Mon, Jul 18, 2011 at 4:01 PM, Brendan Eichbren...@mozilla.com wrote: // replace| with let B = A {...}; // looks like a (prototype) chain link How so? I'm talking about visual similarity with an actual physical chain link. Very visual -- but my mind's eye sees something more like (=) in the right font to line up the round bracket tips with the equals bars... Reasoning about ASCII art, especially with too few chars, is perilous. That link is unidirectional. I don't buy it, I'm thinking of it as the pre-existing (prototype) properties go before the new (own) properties, in other words the spatial and temporal order of the properties matches. Definitely want the prototype object on the left of|. Not sure what else to say. However, I agree with your comment in another post that contextual keywords are worth considering even though they introduce restricted productions. If we were to go that route, I would propose: // replace| with prototypes let B = A prototypes { ... }; That does seem like the keyword to use. It's long, though. // replace with owns let b = B owns { ... }; owns is ambiguous -- could still delegate. Can't use extends, the direction is wrong (and extendedBy is right out!). How about let b = B copies {...}; ? There must be a better contextual keyword... mixin or even Object.extend(src, dest) Dmitry. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Extending standard library of arrays
On 11.07.2011 2:42, David Bruant wrote: Le 10/07/2011 22:46, Dmitry A. Soshnikov a écrit : Here I put some extensions for arrays standard library (separated from this thread: https://mail.mozilla.org/pipermail/es-discuss/2011-July/015856.html where Array.of and Array.from were considered). We can consider also the following (as a first step): *- Array.prototype.remove(value, all)* [1, 2, 3, 2].remove(2); // [1, 3, 2] [1, 2, 3, 2].remove(2, true); // [1, 3] (seems this function is required more than Array.of, because at least I saw it implemented in all frameworks and used it myself). *- Array.prototype.subtract(array)* [1, 2, 3, 4].subtract([2, 4]); // [1, 3] *- Array.seq(from, to)* // or Array.range(from, to) Array.seq(1, 5); // [1, 2, 3, 4, 5] *- Array.build(n, fn)* Array.build(5, function(index) index + 1); // [1, 2, 3, 4, 5] *- Array.min(array), Array.max(array)* (can be implemented with Math.max/min and apply though) Array.min = (array) - Math.min.apply(Math, array) *- Array.prototype.split(n)* [a, b, c, d, e].split(3) // [[a, b, c], [d, e, f]] Perhaps even to build objects from lists of keys and values (this function is usually called as `zip`): *- Object.fromArrays([a, b, c], [1, 2, 3]);* // {a: 1, b: 2, c: 3} *- Array.prototype.unique* [1, 3, 2, 5, 5, 3].unique(); // [1, 3, 2, 5] Thus, all names of methods can be discussed. I like a lot all of these ideas, but I can't help thinking that they do not seem to be aligned with the initial ECMAScript array design which is that arrays are ECMAScript objects (which is very different from what we'd understand of array in C or lists in Erlang as you cite them). The question I ask for each of your Array.prototype ideas is how does it apply to non-dense arrays?. Yes, there is a difference in implementation, but ideologically all these concepts (C's array, JS array, List, etc) stand nearly. E.g. Python's lists are similar to JS arrays. Abstract operations are completely OK -- regardless the implementation and terminology. About the question on sparse (non-dense) arrays -- the answer is -- the same as array methods (e.g. map, forEach, etc) currently do when meat holes -- just skip them. E.g. for remove method: Object.defineProperty(Array.prototype, remove, { value: function (item, all) { for (var k = 0; k this.length; k++) { if (!(k in this)) continue; // support sparse arrays if (this[k] === item) { this.splice(k, 1); if (!all) break; } } return this; }, configurable: true, writable: true }); console.log([1, 2, 3, 4, 2].remove(2)); // [1, 3, 4, 2] console.log([1, 2, 3, 4, 2].remove(2, true)); // [1, 3, 4] // sparse array var data = Array(5); data[3] = 2; data[0] = 1; console.log(data); // [1, , , 2, ] console.log(data.remove(2)); // [1, , , ,] Creating a List or a DenseArray (or both?) type sounds to better capture your intentions (especially since you provided a link to Erlang list methods). I still don't see a big issue with handling sparse arrays as shown above. It's in JS array's nature to be either sparse or dense (regardless implementations of course -- for example, SpiderMonkey may create even a real low-level C's array for this -- [1, 2, 3], but not JS object -- it's dense and contains only numbers -- why not to allocate C's array -- SM does it). It could inherit everything from Array.prototype for free. Actually, this could be implemented with proxies :-) Sure, but we need the case for this. Actually we have already ideas in this direction -- typed arrays, which are effectively dense. Since we're suggesting array additions, I would be interested in trying to address one issue of forEach, map, every, some and filter. They all have a well-defined algorithm. Consequently, if the callback function has side-effects, these are deterministic. This, however, prevent efficient (parallelized, for instance) implementation. This is unfortunate since in a lot of cases, people don't do side-effect and would certainly trade the side-effect determinism guarantee for performance. Could it be considered to add non-deterministic versions of these functions? They would be defined like Array.prototype.sort is, in terms of guarantees (like the callback function will be called at most once on which array element for 'every' and 'some' for instance) rather than with an algorithm. I have no strong opinion on how to name them. Maybe adding an N (for Non-deterministic) at the end of the equivalent method (Array.prototype.forEachN, Array.prototype.mapN, etc.)? We can think on it, though of course a real usage use-cases are required for it. Currently I can say that algorithms of map, forEach, etc are quite logical and how they should be. Do you propose not to check e.g. holes and handle them too? Or to handle elements which were added/removed during the enumeration? Or how the non
Re: Extending standard library of arrays
On 11.07.2011 16:49, David Bruant wrote: Le 11/07/2011 14:29, Dmitry A. Soshnikov a écrit : On 11.07.2011 2:42, David Bruant wrote: Le 10/07/2011 22:46, Dmitry A. Soshnikov a écrit : Here I put some extensions for arrays standard library (separated from this thread: https://mail.mozilla.org/pipermail/es-discuss/2011-July/015856.html where Array.of and Array.from were considered). We can consider also the following (as a first step): *- Array.prototype.remove(value, all)* [1, 2, 3, 2].remove(2); // [1, 3, 2] [1, 2, 3, 2].remove(2, true); // [1, 3] (seems this function is required more than Array.of, because at least I saw it implemented in all frameworks and used it myself). *- Array.prototype.subtract(array)* [1, 2, 3, 4].subtract([2, 4]); // [1, 3] *- Array.seq(from, to)* // or Array.range(from, to) Array.seq(1, 5); // [1, 2, 3, 4, 5] *- Array.build(n, fn)* Array.build(5, function(index) index + 1); // [1, 2, 3, 4, 5] *- Array.min(array), Array.max(array)* (can be implemented with Math.max/min and apply though) Array.min = (array) - Math.min.apply(Math, array) *- Array.prototype.split(n)* [a, b, c, d, e].split(3) // [[a, b, c], [d, e, f]] Perhaps even to build objects from lists of keys and values (this function is usually called as `zip`): *- Object.fromArrays([a, b, c], [1, 2, 3]);* // {a: 1, b: 2, c: 3} *- Array.prototype.unique* [1, 3, 2, 5, 5, 3].unique(); // [1, 3, 2, 5] Thus, all names of methods can be discussed. I like a lot all of these ideas, but I can't help thinking that they do not seem to be aligned with the initial ECMAScript array design which is that arrays are ECMAScript objects (which is very different from what we'd understand of array in C or lists in Erlang as you cite them). The question I ask for each of your Array.prototype ideas is how does it apply to non-dense arrays?. Yes, there is a difference in implementation, but ideologically all these concepts (C's array, JS array, List, etc) stand nearly. E.g. Python's lists are similar to JS arrays. Abstract operations are completely OK -- regardless the implementation and terminology. About the question on sparse (non-dense) arrays -- the answer is -- the same as array methods (e.g. map, forEach, etc) currently do when meat holes -- just skip them. E.g. for remove method: Object.defineProperty(Array.prototype, remove, { value: function (item, all) { for (var k = 0; k this.length; k++) { if (!(k in this)) continue; // support sparse arrays if (this[k] === item) { this.splice(k, 1); if (!all) break; } } return this; }, configurable: true, writable: true }); console.log([1, 2, 3, 4, 2].remove(2)); // [1, 3, 4, 2] console.log([1, 2, 3, 4, 2].remove(2, true)); // [1, 3, 4] // sparse array var data = Array(5); data[3] = 2; data[0] = 1; console.log(data); // [1, , , 2, ] console.log(data.remove(2)); // [1, , , ,] So .length is kept from the initial array? If so, then: console.log([1, 2, 3, 4, 2].remove(2)); // [1, 3, 4, 2, ] // added empty element No, the length is modified in this particular case by removing the items. I missed in output in first case, should be [1, , , , 2, ] and then [1, , , ,]. I.e. just 2 is removed, and length is decremented, all other positions are kept. Creating a List or a DenseArray (or both?) type sounds to better capture your intentions (especially since you provided a link to Erlang list methods). I still don't see a big issue with handling sparse arrays as shown above. It's in JS array's nature to be either sparse or dense (regardless implementations of course -- for example, SpiderMonkey may create even a real low-level C's array for this -- [1, 2, 3], but not JS object -- it's dense and contains only numbers -- why not to allocate C's array -- SM does it). It could inherit everything from Array.prototype for free. Actually, this could be implemented with proxies :-) Sure, but we need the case for this. Actually we have already ideas in this direction -- typed arrays, which are effectively dense. The idea of creating a non-sparse array type is indeed in between the additions of high-level abstractions (maps and sets) and what is done in typed arrays which are dense by nature. Since we're suggesting array additions, I would be interested in trying to address one issue of forEach, map, every, some and filter. They all have a well-defined algorithm. Consequently, if the callback function has side-effects, these are deterministic. This, however, prevent efficient (parallelized, for instance) implementation. This is unfortunate since in a lot of cases, people don't do side-effect and would certainly trade the side-effect determinism guarantee for performance. Could it be considered to add non-deterministic versions of these functions? They would be defined like Array.prototype.sort is, in terms
Re: Pure win: Array.from and Array.of
On 11.07.2011 20:01, Allen Wirfs-Brock wrote: On Jul 10, 2011, at 12:09 PM, Dmitry A. Soshnikov wrote: And by the way, an efficient `Array.prototype.unique` also would be nice to have, since in JS in general it's hard to implement it's efficiently (in lower level at least it will iterate faster). [1, 3, 2, 5, 5, 3].unique(); // [1, 3, 2, 5] Before considering adding too many things to Array.prototype I wouldn't call such standard methods which are present in standard libraries of many languages as too many things. we perhaps should start considering the protocol of a real collection hierarchy that goes beyond just arrays. Yes, and this is of course true. Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Summary: prototypes as classes
On 12.07.2011 0:18, Bob Nystrom wrote: I agree with Brendan's replies, but just to add some more color: On Sat, Jul 2, 2011 at 11:46 AM, Angus Croll anguscr...@gmail.com mailto:anguscr...@gmail.com wrote: The concept itself is very simple - a dynamic archetype to be shared by all my instances: my prototype changes, my instances know about it. I would not want to hide such a smart, simple concept behind the more complex and (in this scenario) less meaningful concept of class. To me, that's pretty close to a class: a thing that describes the properties and behavior of a set of objects. Sure, you can roll in all of the other shenanigans that Java et. al. include (final, static, nested classes, etc.) but the real kernel is we have a bunch of objects that are similar and we want to define that similarity in one place. JS does so through MyType.prototype and class-based languages do it in a class definition. The class syntax proposal just gives you a nicer notation for the former. It turns our that making decisions though the prism of some concrete _implementation_, programmers make incorrect judgment about some _techniques_ of code reuse. Ideological code reuse class may have several implementations. In static second-class classes, it can be method-calls technique with static (and known) addresses. In contrast in first-class dynamic systems it can be message passing technique based on delegation (i.e. based on prototypes). But still, _regardless implementation_, the concept of a class assumes just a _classified code_ reuse, no more, no less. That is, (1) creation of many instances with the same state, (2) ability to mark the instances with the classification tag. Thus, the (2) is not even required. Once you've started to create many instances with the same state -- you already program with the concept of a class, i.e. using classified code reuse. E.g.: var pointA= {x: 10, y: 20}; var pointB= {x: 30, y: 40}; var pointC= {x: 50, y: 60}; I already created (in mind, virtually) the concept of a point class. That's it. And all the other stuff -- is just the _syntactic improvements_ of this concept. There no other reasons. Just very practical reason -- efficient code reuse. Don't wanna write this copy-pasted points -- move them to a function (as you always do, when a code is repeated more than two times) -- and you get constructors of JS. Don't like that classification is called not with the word class -- rename it to class and add another sugar. So -- just the sugar matters. And without the sugar, that's said -- only practical code reuse technique. I hope this small table will help: https://gist.github.com/977034 Once again -- statics method-calls vs. dynamics and delegation/message passing -- are just the techniques. But a class is a concept, which can be implemented in any form. From this viewpoint JS had, have, and will have (sugared now) classes. Because a class is not a special keyword class in a lang, it's not the ability to create classes with this keyword, but class -- is _the ability to classify_. And how it's done -- either with class keyword or with the function keyword -- absolutely doesn't matter. P.S.: regarding concept of mixins -- JS (starting form the time, when Object.extend was borrowed from Ruby to Prototype.js) has currently static mixins with copying own properties. In the same Ruby mixins are delegation-based, that is no more than just many prototypes mixed to an object -- change a mixed module, and all instances which are included the module will see these changes -- pure delegation. P.S[1]: the same with Python. Once it has a sugar called class novices on comp.sci call it class-based. But in fact, Python is prototype-based language, i.e. delegation-based with classes as sugar. The same as in CoffeeScript, the same as planned for ECMAScript. So there is nothing to scary. Dmitry. a) The syntax may be fixable but the logic isn't. Inheritance hierarchies are gnarly. - Nine times out of ten it's a re-use technique masquerading as a classification of types. Agreed, completely. Deep inheritance hierachies are almost always a guarantee of misery. But the 1 in 10 case where OOP inheritance has been a big success is... UI frameworks. Considering how important that use case is to JavaScript, supporting it gracefully seems reasonable to me. - Mixins allow objects to borrow from an unlimited number of other objects regardless of lineage, while still allowing for organization of functions by type. I'm a huge fan of mixins/traits/multiple-inheritance (http://journal.stuffwithstuff.com/2011/02/21/multiple-inheritance-in-javascript/). I very often find single inheritance frustrating. I don't like classic mixins because they make it too easy for a later mixin to stomp over the methods of an earlier one. Traits solve that nicely, and I'd like to see them in JS at some
Re: Pure win: Array.from and Array.of
Array.from is a good addition, I guess any good framework has it. Though, `Array.of` in contrast doesn't bring much of a sugar. Compare these two apples-to-apples: Array.of( things, that, aren't, currently, an, array ) vs. [things, that, aren't, currently, an, array] what's the goal in first case to write this useless Array.of prefix and exactly the same to manually enumerate the items? In fact, the second one is more suggared than the first one (the first one is: added useless prefix Array.of and brackets around items are replaced with call parens). Another thing to consider is `Array.prototype.fill` method which we discussed before. The problem: Array(4).map(function(x) x * x); // [NaN, NaN, NaN, NaN] (by the way, this mistaken example is still mentioned in this document http://wiki.ecmascript.org/doku.php?id=strawman:shorter_function_syntax, in the Alternate Syntax Proposals section, though, is fixed in the main section with `let randomArray = NonHoleyArray(10).map(#{Math.random()});` when was mentioned before). The solution: // fill with a simple value Array(4).fill(true); // [true, true, true, true] // fill with a function in needed context of this let object = {data: 4}; Array(3).fill(- if this.data 3 { 'accepted' } else {'declined' }, object); Implementation is quite simple also, though, can be optimized in built-ins: Array.prototype.fill || Object.defineProperty(Array.prototype, fill, { valu: function arrayFill(filler) { for (var k = 0; k this.length; k++) { this[k] = typeof filler == function ? filler.call(thisArg || this, this[k], k, this) : value; } return this; }, configurable: true, writable: true }); Also class-method Array.fill(count, filler) can be considered. Dmitry. On 10.07.2011 9:35, Brendan Eich wrote: Thanks to @rwaldron for compiling these, and dherman (@littlecalculist) for being a twitter conversationalist who speaks in JS: https://gist.github.com/1074126 http://jsfiddle.net/rwaldron/5UjWy/ From a twitter conversation sparked by an IRC conversation where I reminded jcran...@mozilla.com mailto:jcran...@mozilla.com that ES5 Function.prototype.bind can be used to spread arguments into a 'new' expression. Standardizing these would save reinventing them, and the built-ins could be optimized quite a bit. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Pure win: Array.from and Array.of
On 10.07.2011 14:27, Mike Shaver wrote: On Sun, Jul 10, 2011 at 6:06 AM, Dmitry A. Soshnikov dmitry.soshni...@gmail.com wrote: The problem: Array(4).map(function(x) x * x); // [NaN, NaN, NaN, NaN] I think it actually produces just [ , , , , ], because map skips holes. (If you see the NaN behaviour in FF, please file a bug.) Sorry, did I wrote NaN? A hole of course (i.e. nothing), which is by [[Get]] is displayed as `undefined` in Firebug, or just as just with toString. Anyway, the issue is in its behavior. If I hadn't made map skip holes, then the fill pattern would be simple enough: Array(4).map(function (_,x) x * x); It's in particular case, you try to multiply indices, which in current implementation of `map` anyway gives unfortunately nothing. Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Pure win: Array.from and Array.of
On 10.07.2011 15:14, Mike Shaver wrote: On Sun, Jul 10, 2011 at 7:09 AM, Dmitry A. Soshnikov dmitry.soshni...@gmail.com wrote: If I hadn't made map skip holes, then the fill pattern would be simple enough: Array(4).map(function (_,x) x * x); It's in particular case, you try to multiply indices, which in current implementation of `map` anyway gives unfortunately nothing. Yes, as I said it *would* work if map had been specified not to skip holes: Oh, *would* -- I missed it. Sure, but if it *had*, I *wouldn't* mention it at all ;) But `map` correctly skips holes, as it should -- to support sparse arrays. The issue is not in `map`, so that's why I mention `fill`. Dmitry. js [undefined,undefined,undefined,undefined].map(function(_,x)x*x) [0, 1, 4, 9] Is that not what you want? Mike ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array generation
On 10.07.2011 15:54, David Bruant wrote: Le 10/07/2011 12:06, Dmitry A. Soshnikov a écrit : (...) Another thing to consider is `Array.prototype.fill` method which we discussed before. The problem: Array(4).map(function(x) x * x); // [NaN, NaN, NaN, NaN] (by the way, this mistaken example is still mentioned in this document http://wiki.ecmascript.org/doku.php?id=strawman:shorter_function_syntax, in the Alternate Syntax Proposals section, though, is fixed in the main section with `let randomArray = NonHoleyArray(10).map(#{Math.random()});` when was mentioned before). The solution: // fill with a simple value Array(4).fill(true); // [true, true, true, true] // fill with a function in needed context of this let object = {data: 4}; Array(3).fill(- if this.data 3 { 'accepted' } else {'declined' }, object); What is Array(9).fill(function(){})? An array filled with 9 undefined? An array filled with 9 (no-op) functions? 9 undefined according to the implementation you provided. I think it should be 9 functions. It's a good question. Though, usually it's needed to initiate an array just with a simple value, so the case with a function (as a filler) was provided as just an addition. From this viewpoint, yes, perhaps it should 9 functions. Another syntax should be provided to generate values with a function. Maybe: Array.generate(count, fillerFunction/*throws a TypeError if not callable*/, thisArg) (call count times fillerFunction.bind(thisArg) and return value of i-th call is [[Put]] as i-th element of the array) Array.fill could be implemented as: Array.fill = function(c, v){ return Array.generate(c, (- v) ); }; Yes, it's common way, though, that's said, usually it's needed only to fill an array with e.g. Array.fill(1) So from this viewpoint (and regarding that example with squares), it's good to have also `Array.seq(from, to)` method (the name is taken from Erlang, I just frequently uses lists:seq(from, to) there): Array.seq(1, 5).map((x) - x * x); [1, 4, 9, 16, 25] (...) Also class-method Array.fill(count, filler) can be considered. Since .fill seems to be intended for initialization, I would tend to be in favor of an Array.fill method rather than Array.prototype.fill. But a Array.fill syntax would prevent from choosing the prototype. Maybe harmony:array_comprehensions could be enhanced to support array generation? Since I'm not familiar with the proposal, I won't try to play with the grammar, but it sounds like the right place to suggest initialization syntax. And it would solve the prototype issue in combination with the proto operator: myProto| [/*my syntax generating an array of 1000 elements*/] Yes, also have to consider it and think. Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Pure win: Array.from and Array.of
On 10.07.2011 20:36, Brendan Eich wrote: On Jul 10, 2011, at 3:06 AM, Dmitry A. Soshnikov wrote: Array.from is a good addition, I guess any good framework has it. Though, `Array.of` in contrast doesn't bring much of a sugar. Compare these two apples-to-apples: Array.of( things, that, aren't, currently, an, array ) vs. [things, that, aren't, currently, an, array] what's the goal in first case to write this useless Array.of prefix and exactly the same to manually enumerate the items? In fact, the second one is more suggared than the first one (the first one is: added useless prefix Array.of and brackets around items are replaced with call parens). Note that JS's pattern for alternative constructors is String.fromCharCode, Array.from, etc. -- class methods. Yes, that's OK with `Array.from`. That's said, many libs have such a util. Some langs, e.g. Ruby just expose such a possibility as instance method. That is, an object there can just call its inherited method `to_a` to convert `self` to array value. Though, `Array.from(...)` seems better for JS for the same reason as `Object.defineProperty` is placed on `Object` instead of the `Object.prototype`. So the goal of Array.of is to provide a constructor that, unlike Array, does not have that insane special case for Array(42), which presets length (and hints to implementations to preallocate) but leaves holes in [0, length). I still don't see how it will help in manual enumeration of the same items which may be directly passed to brackets of array initialiser. We enumerate (by hands) items here, right? -- Array.of(1, 2, 3). And we enumerate items here (by hands also) -- [1, 2, 3]. The difference is that the second case syntactically more elegant and sugared and also doesn't require non-needed function activation with allocating call-stack frame, etc. Still `Array.of` seems just useless for me. Correct me if I'm wrong. But I'm all in for the `Array.from`. Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Pure win: Array.from and Array.of
On 10.07.2011 21:18, Brendan Eich wrote: On Jul 10, 2011, at 9:59 AM, Dmitry A. Soshnikov wrote: On 10.07.2011 20:36, Brendan Eich wrote: So the goal of Array.of is to provide a constructor that, unlike Array, does not have that insane special case for Array(42), which presets length (and hints to implementations to preallocate) but leaves holes in [0, length). I still don't see how it will help in manual enumeration of the same items which may be directly passed to brackets of array initialiser. We enumerate (by hands) items here, right? -- Array.of(1, 2, 3). And we enumerate items here (by hands also) -- [1, 2, 3]. The difference is that the second case syntactically more elegant and sugared and also doesn't require non-needed function activation with allocating call-stack frame, etc. That's all true, but beside the point. The use-case is when you can't write a literal, because you are passing a function-that-constructs as a funarg, and the eventual caller may pass only one number arg, or several args. In that case, Array will not do the right thing in the one-number-arg case. You mean Function.prototype.construct (http://dmitrysoshnikov.com/notes/note-1-ecmascript-bound-functions/#constructor-with-various-number-of-arguments)? In this case spread operator will help and some additional thing for this is not required. That's the reason for Array.of. Could you please show an example? From what I understand from your words it's sort of: function Foo(a, b) { ... } var object = (function (ConstructorFunction, a, b) { return new ConstructorFunction /* here Array.of should help some how to pass `a` and `b` - how? */ })(Foo, 10, 20); Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Pure win: Array.from and Array.of
On 10.07.2011 21:32, Allen Wirfs-Brock wrote: On Jul 10, 2011, at 10:23 AM, Brendan Eich wrote: On Jul 10, 2011, at 10:18 AM, Rick Waldron wrote: The more I think about it, I still can't come up with any really exciting use cases where Array.of http://Array.of/ would outshine anything that already exists. I say strike it from the wishlist. Higher-order programming with Array as constructing-function bites back for the single-number-argument case. That's where Array.of helps. Yes, if you actually need to pass Array.of as a function argument. Of course if we have block lambdas you could just say: hof({|a|[a]}) instead of hof(Array.of) Can you show a real use-case of it please? Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Pure win: Array.from and Array.of
And I don't see it still. Maybe you can explain it in some detail then if you have understood it? Dmitry. On 10.07.2011 21:33, Rick Waldron wrote: _that_ is the compelling use-case I was looking for. Rick -- Sent from my Palm Pre On Jul 10, 2011 1:23 PM, Brendan Eich bren...@mozilla.com wrote: On Jul 10, 2011, at 10:18 AM, Rick Waldron wrote: The more I think about it, I still can't come up with any really exciting use cases where Array.of http://Array.of/ would outshine anything that already exists. I say strike it from the wishlist. Higher-order programming with Array as constructing-function bites back for the single-number-argument case. That's where Array.of helps. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Pure win: Array.from and Array.of
On 10.07.2011 22:26, John-David Dalton wrote: I dig Array.from, and have manually made sugar for that in my projects. Array.of is something I have also wanted though I had been struggling with a name for it. It's interesting -- can you show where and how? Until now if I wanted to avoid setting the array length I would do something like ns.Array.from([23]), What. Is. That. ? Isn't just [23] is enough? Guys, I understand we need `Array.from` as a good addition. Note -- it's just the addition to be able use array methods. We though can do it and without it via call and apply since most of array methods are generic. but Array.of is nice too ;) Can maybe you show me a real useful example of Arra.of? Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Pure win: Array.from and Array.of
On 10.07.2011 22:44, Brendan Eich wrote: On Jul 10, 2011, at 10:40 AM, Dmitry A. Soshnikov wrote: On 10.07.2011 21:23, Brendan Eich wrote: On Jul 10, 2011, at 10:18 AM, Rick Waldron wrote: The more I think about it, I still can't come up with any really exciting use cases where Array.of http://Array.of/ would outshine anything that already exists. I say strike it from the wishlist. Higher-order programming with Array as constructing-function bites back for the single-number-argument case. That's where Array.of helps. You mean when `Array` itself is passed as an argument? var o = (function (ArrayConstructor, ...rest) { return ArrayConstructor(...rest); })(Array, 10, 20, 30); Yes. Now consider the case where you leave out the 20 and 30. return ArrayConstructor(rest[0]) ? May I ask to show nevertheless how you want to apply here Array.of? P.S.: If this is a wish-list of extending standard array lib, we can consider also the following: - Array.prototype.remove(value, all) [1, 2, 3, 2].remove(2); // [1, 3, 2] [1, 2, 3, 2].remove(2, true); // [1, 3] (seems this function is required more than Array.of, because at least I saw it implemented in all frameworks and used it myself). - Array.prototype.subtract(array) [1, 2, 3, 4].subtract([2, 4]); // [1, 3] - Array.seq(from, to) Array.seq(1, 5); // [1, 2, 3, 4, 5] - Array.min(array), Array.max(array) (can be implemented with Math.max/min and apply though) Array.min = (array) - Math.min.apply(Math, array) - Array.prototype.split(n) [a, b, c, d, e].split(3) // [[a, b, c], [d, e, f]] Perhaps even to build objects from lists of keys and values (this function is usually called as `zip`): - Object.fromLists([a, b, c], [1, 2, 3]); // {a: 1, b: 2, c: 3} Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Pure win: Array.from and Array.of
And by the way, an efficient `Array.prototype.unique` also would be nice to have, since in JS in general it's hard to implement it's efficiently (in lower level at least it will iterate faster). [1, 3, 2, 5, 5, 3].unique(); // [1, 3, 2, 5] Dmitry. On 10.07.2011 23:02, Dmitry A. Soshnikov wrote: On 10.07.2011 22:44, Brendan Eich wrote: On Jul 10, 2011, at 10:40 AM, Dmitry A. Soshnikov wrote: On 10.07.2011 21:23, Brendan Eich wrote: On Jul 10, 2011, at 10:18 AM, Rick Waldron wrote: The more I think about it, I still can't come up with any really exciting use cases where Array.of http://Array.of/ would outshine anything that already exists. I say strike it from the wishlist. Higher-order programming with Array as constructing-function bites back for the single-number-argument case. That's where Array.of helps. You mean when `Array` itself is passed as an argument? var o = (function (ArrayConstructor, ...rest) { return ArrayConstructor(...rest); })(Array, 10, 20, 30); Yes. Now consider the case where you leave out the 20 and 30. return ArrayConstructor(rest[0]) ? May I ask to show nevertheless how you want to apply here Array.of? P.S.: If this is a wish-list of extending standard array lib, we can consider also the following: - Array.prototype.remove(value, all) [1, 2, 3, 2].remove(2); // [1, 3, 2] [1, 2, 3, 2].remove(2, true); // [1, 3] (seems this function is required more than Array.of, because at least I saw it implemented in all frameworks and used it myself). - Array.prototype.subtract(array) [1, 2, 3, 4].subtract([2, 4]); // [1, 3] - Array.seq(from, to) Array.seq(1, 5); // [1, 2, 3, 4, 5] - Array.min(array), Array.max(array) (can be implemented with Math.max/min and apply though) Array.min = (array) - Math.min.apply(Math, array) - Array.prototype.split(n) [a, b, c, d, e].split(3) // [[a, b, c], [d, e, f]] Perhaps even to build objects from lists of keys and values (this function is usually called as `zip`): - Object.fromLists([a, b, c], [1, 2, 3]); // {a: 1, b: 2, c: 3} Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Pure win: Array.from and Array.of
On 10.07.2011 23:09, Dmitry A. Soshnikov wrote: And by the way, an efficient `Array.prototype.unique` also would be nice to have, since in JS in general it's hard to implement it's efficiently (in lower level at least it will iterate faster). [1, 3, 2, 5, 5, 3].unique(); // [1, 3, 2, 5] Dmitry. On 10.07.2011 23:02, Dmitry A. Soshnikov wrote: On 10.07.2011 22:44, Brendan Eich wrote: On Jul 10, 2011, at 10:40 AM, Dmitry A. Soshnikov wrote: On 10.07.2011 21:23, Brendan Eich wrote: On Jul 10, 2011, at 10:18 AM, Rick Waldron wrote: The more I think about it, I still can't come up with any really exciting use cases where Array.of http://Array.of/ would outshine anything that already exists. I say strike it from the wishlist. Higher-order programming with Array as constructing-function bites back for the single-number-argument case. That's where Array.of helps. You mean when `Array` itself is passed as an argument? var o = (function (ArrayConstructor, ...rest) { return ArrayConstructor(...rest); })(Array, 10, 20, 30); Yes. Now consider the case where you leave out the 20 and 30. return ArrayConstructor(rest[0]) ? Ah, goddammit, sorry, I got it. Completely forgot about this case, even if myself just showed it before in Array(42).map example, thanks for mentioning. It will of course create array with length 10 and with holes (some implementations, in particular V8 even pre-allocate these holes). So Array.of is just exactly and only for this use-case. Dmitry. May I ask to show nevertheless how you want to apply here Array.of? P.S.: If this is a wish-list of extending standard array lib, we can consider also the following: - Array.prototype.remove(value, all) [1, 2, 3, 2].remove(2); // [1, 3, 2] [1, 2, 3, 2].remove(2, true); // [1, 3] (seems this function is required more than Array.of, because at least I saw it implemented in all frameworks and used it myself). - Array.prototype.subtract(array) [1, 2, 3, 4].subtract([2, 4]); // [1, 3] - Array.seq(from, to) Array.seq(1, 5); // [1, 2, 3, 4, 5] - Array.min(array), Array.max(array) (can be implemented with Math.max/min and apply though) Array.min = (array) - Math.min.apply(Math, array) - Array.prototype.split(n) [a, b, c, d, e].split(3) // [[a, b, c], [d, e, f]] Perhaps even to build objects from lists of keys and values (this function is usually called as `zip`): - Object.fromLists([a, b, c], [1, 2, 3]); // {a: 1, b: 2, c: 3} Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Pure win: Array.from and Array.of
On 10.07.2011 23:25, Juan Ignacio Dopazo wrote: On Sun, Jul 10, 2011 at 2:35 PM, Dmitry A. Soshnikov dmitry.soshni...@gmail.com mailto:dmitry.soshni...@gmail.com wrote: On 10.07.2011 21:32, Allen Wirfs-Brock wrote: On Jul 10, 2011, at 10:23 AM, Brendan Eich wrote: On Jul 10, 2011, at 10:18 AM, Rick Waldron wrote: The more I think about it, I still can't come up with any really exciting use cases where Array.of http://Array.of/ would outshine anything that already exists. I say strike it from the wishlist. Higher-order programming with Array as constructing-function bites back for the single-number-argument case. That's where Array.of helps. Yes, if you actually need to pass Array.of as a function argument. Of course if we have block lambdas you could just say: hof({|a|[a]}) instead of hof(Array.of) Can you show a real use-case of it please? Dmitry. A real use-case for this functions: http://yuilibrary.com/forum/viewtopic.php?f=18t=7978 http://yuilibrary.com/forum/viewtopic.php?f=18t=7978 YUI uses get/set methods for dealing with attributes and has a declarative form for them that looks like this: Y.SomeClass = Y.Base.create('someClass', Y.Superclass, [Y.Mixin], proto, { ATTRS: { someAttr: { value: [] } } }); Using [] as a default value can lead to bugs because the class will hold a reference to a unique array in all instances. Using a constructor function one can be sure each instance will have a fresh array. Y.SomeClass = Y.Base.create('someClass', Y.Superclass, [Y.Mixin], proto, { ATTRS: { someAttr: { valueFn: Array } } }); Here valueFn calls the provided function to create the default value each time. In this case it would create a new array. Array creation functions would help create more complex patters and avoid bugs with unexpected parametes (tough now I think Array.bind(null, 0) maybe could work... I see. Though, the case with `Array.bind(null, 0)` seems is particular for YUI. Anyway, from what I can say now `Array.of` is a fixed version of `Array` which doesn't have a special case of `Array(length)`, but always considers it as Array(items...). Don't know how rare/often this case is. Sometimes it's needed vice-versa to create Array(length). I also think we should consider other proposals of arrays library which I mentioned in previous letter. Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Pure win: Array.from and Array.of
On 11.07.2011 0:35, Brendan Eich wrote: On Jul 10, 2011, at 12:02 PM, Dmitry A. Soshnikov wrote: On 10.07.2011 22:44, Brendan Eich wrote: On Jul 10, 2011, at 10:40 AM, Dmitry A. Soshnikov wrote: On 10.07.2011 21:23, Brendan Eich wrote: On Jul 10, 2011, at 10:18 AM, Rick Waldron wrote: The more I think about it, I still can't come up with any really exciting use cases where Array.of http://Array.of/ would outshine anything that already exists. I say strike it from the wishlist. Higher-order programming with Array as constructing-function bites back for the single-number-argument case. That's where Array.of helps. You mean when `Array` itself is passed as an argument? var o = (function (ArrayConstructor, ...rest) { return ArrayConstructor(...rest); })(Array, 10, 20, 30); Yes. Now consider the case where you leave out the 20 and 30. return ArrayConstructor(rest[0]) ? The called function taking ArrayConstructor cannot assume it was passed only one trailing parameter captured by ...rest! May I ask to show nevertheless how you want to apply here Array.of? You would pass Array.of instead of Array, of course. Yes, I've already realized it. Array.of is just a fixed version of Array. Though, I'm still thinking how rare/often these cases are. P.S.: If this is a wish-list of extending standard array lib, we can consider also the following: A postscript is no place for more wish list items. See the subject: and start a new thread. Yes, OK, it will be better. Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Extending standard library of arrays
Here I put some extensions for arrays standard library (separated from this thread: https://mail.mozilla.org/pipermail/es-discuss/2011-July/015856.html where Array.of and Array.from were considered). We can consider also the following (as a first step): *- Array.prototype.remove(value, all)* [1, 2, 3, 2].remove(2); // [1, 3, 2] [1, 2, 3, 2].remove(2, true); // [1, 3] (seems this function is required more than Array.of, because at least I saw it implemented in all frameworks and used it myself). *- Array.prototype.subtract(array)* [1, 2, 3, 4].subtract([2, 4]); // [1, 3] *- Array.seq(from, to)* // or Array.range(from, to) Array.seq(1, 5); // [1, 2, 3, 4, 5] *- Array.build(n, fn)* Array.build(5, function(index) index + 1); // [1, 2, 3, 4, 5] *- Array.min(array), Array.max(array)* (can be implemented with Math.max/min and apply though) Array.min = (array) - Math.min.apply(Math, array) *- Array.prototype.split(n)* [a, b, c, d, e].split(3) // [[a, b, c], [d, e, f]] Perhaps even to build objects from lists of keys and values (this function is usually called as `zip`): *- Object.fromArrays([a, b, c], [1, 2, 3]);* // {a: 1, b: 2, c: 3} *- Array.prototype.unique* [1, 3, 2, 5, 5, 3].unique(); // [1, 3, 2, 5] Thus, all names of methods can be discussed. Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Extending standard library of arrays
In addition, here's Erlang's one, which has rich lists library -- http://www.erlang.org/doc/man/lists.html Some/most methods are already implemented in JS of course (though, by different names), but we can take missing, but needed (and thus implemented in many JS libs) methods. Dmitry. On 11.07.2011 0:46, Dmitry A. Soshnikov wrote: Here I put some extensions for arrays standard library (separated from this thread: https://mail.mozilla.org/pipermail/es-discuss/2011-July/015856.html where Array.of and Array.from were considered). We can consider also the following (as a first step): *- Array.prototype.remove(value, all)* [1, 2, 3, 2].remove(2); // [1, 3, 2] [1, 2, 3, 2].remove(2, true); // [1, 3] (seems this function is required more than Array.of, because at least I saw it implemented in all frameworks and used it myself). *- Array.prototype.subtract(array)* [1, 2, 3, 4].subtract([2, 4]); // [1, 3] *- Array.seq(from, to)* // or Array.range(from, to) Array.seq(1, 5); // [1, 2, 3, 4, 5] *- Array.build(n, fn)* Array.build(5, function(index) index + 1); // [1, 2, 3, 4, 5] *- Array.min(array), Array.max(array)* (can be implemented with Math.max/min and apply though) Array.min = (array) - Math.min.apply(Math, array) *- Array.prototype.split(n)* [a, b, c, d, e].split(3) // [[a, b, c], [d, e, f]] Perhaps even to build objects from lists of keys and values (this function is usually called as `zip`): *- Object.fromArrays([a, b, c], [1, 2, 3]);* // {a: 1, b: 2, c: 3} *- Array.prototype.unique* [1, 3, 2, 5, 5, 3].unique(); // [1, 3, 2, 5] Thus, all names of methods can be discussed. Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Writing a desktop app in JavaScript?
Nevertheless, IMO this list is mostly for ES design. Practical JS application and tools better discuss in e.g. jsmentors list. Dmitry. On 03.07.2011 20:27, Axel Rauschmayer wrote: I hope the following question is not too out of place on this mailing list: JavaScript would really profit from a simple environment for writing desktop applications, especially for tasks that you would normally use shell scripts for. I like that such an environment would make it incredibly easy to add a cross-platform GUI. Can anyone recommend a good environment for writing desktop apps in JavaScript and HTML5? Requirements: - Read/write access to the local file system. - Download any file from the web (even from servers that don’t support CORS). - Ease of development: no extra build step before you can run your app. - Use HTML5 for the GUI. So far, I’ve looked at: 1. Adobe Air: needs the AIR runtime. 2. Google Chrome: comes pretty close: you can get read access to all files in a folder that you “upload” via a form; you can switch off cross-site restrictions via a flag; you can use the FileSystem API to write files and copy them back, out of the sandbox later. There are extensions, but those require a build step which makes it painful to develop them. 3. XULRunner: seems to require XUL. 4. Firefox Add-On: not geared towards desktop apps. 5. Node.js + GUI in a browser via a localhost URL: Cannot be packaged nicely, having to chose a port is problematic (usability, clashes). 6. Titanium Desktop: ready yet? (1) and (5) look like the most practical solutions that are currently available. Any other suggestions or experiences with the above solutions? ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Is class syntax really necessary ?
On 13.06.2011 1:18, Brendan Eich wrote: On Jun 12, 2011, at 2:22 AM, Irakli Gozalishvili wrote: Hi, Is there anything else (other than starting this thread) I can do to make committee consider `Function.prototype.extend` as an alternative to a proposed class sugar ? Could you show Function.prototype.extend again, and say how it solves the super-construct and super-method-call problems? If interested, I know at least three versions of normal `super` sugar in ES3 code: 1. using wrappers for every descendant method with the same name (the technique is to (a) set `this.super` to parent, (b) activate parent method and get result, (c) return result to child) 2. using `Object.prototype` to store `super` 3. using `arguments.caller` (banned in ES5-strict, non-standard in ES3, but I normally used it in my projects) If will be needed, I can write the code for all three techniques (the later though can be found here: https://github.com/DmitrySoshnikov/def.js/blob/master/def.js#L80 That is, it's not actually the main issue, we normally can write in ES3/5 code something like this: var Foo = Class({ constructor: function (a) { this.a = a; }, activate: function () { return this.a; } }); var Bar = Class({ constructor: function (a, b) { this.super(a); this.b = b; }, activate: function () { console.log(this.b + this.super()); } }); var bar = new Bar(10, 20); bar.activate(); // 30! P.S.: of course this.super() is much more convenient than (real code from e.g. ExtJS) `Bar.superclass.constructor.apply(this, arguments)` (what? are you kidding me, guys? Seems you just like syntactic noise). But unfortunately because of hack-nature (`caller` is not-standard and banned, people afraid to augment `Object.prototype`, wrappers are not so efficient), so it's not e.g. for cross-browser code. Though, I was pleased to use it in my library in the project where I had SpiderMonkey-only stuff (patched Thunderbird), so there I used that `this.super` actively (OK, actually `this._super`, because only since ES5 we can use keywords as properties). However, regardless that we _can_ implement convinient and sugared super calls as a library, classes from the box will be more convenient IMO. Dmitry. /be Thanks -- Irakli Gozalishvili Web: http://www.jeditoolkit.com/ Address: 29 Rue Saint-Georges, 75009 Paris, France http://goo.gl/maps/3CHu On Tuesday, 2011-05-24 at 24:48 , Brendan Eich wrote: On May 23, 2011, at 11:25 AM, Bob Nystrom wrote: One thing I'd like the proposal to support, which it doesn't currently, is initializers on instance property declarations. Then you could do: class C { public _list = []; } With that, you'll correctly get a new _list on each instance of C when it's created. But (we've argued, I forget where so repeating it here), this looks like [] is evaluated once when the class declaration is evaluated. That is not what you intend. Then at some point (in the last thread on this) I remembered parameter default values, but they cover only missing parameters to the constructor. This _list member could be private. But it has to be initialized in a body that executes once per instantiation, which is not the class body -- it's the constructor body. /be ___ es-discuss mailing list es-discuss@mozilla.org mailto:es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org mailto:es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Is class syntax really necessary ?
On 13.06.2011 1:43, Dmitry A. Soshnikov wrote: On 13.06.2011 1:18, Brendan Eich wrote: On Jun 12, 2011, at 2:22 AM, Irakli Gozalishvili wrote: Hi, Is there anything else (other than starting this thread) I can do to make committee consider `Function.prototype.extend` as an alternative to a proposed class sugar ? Could you show Function.prototype.extend again, and say how it solves the super-construct and super-method-call problems? If interested, I know at least three versions of normal `super` sugar in ES3 code: 1. using wrappers for every descendant method with the same name (the technique is to (a) set `this.super` to parent, (b) activate parent method and get result, (c) return result to child) 2. using `Object.prototype` to store `super` 3. using `arguments.caller` (banned in ES5-strict, non-standard in ES3, but I normally used it in my projects) If will be needed, I can write the code for all three techniques (the later though can be found here: https://github.com/DmitrySoshnikov/def.js/blob/master/def.js#L80 Forgot to mention example: def (Person) ({ init: function (name) { this.name = name; }, speak: function (text) { alert(text || Hi, my name is + this.name); } }); def (Ninja) Person ({ init: function (name) { this.base(name); }, kick: function () { this.speak(I kick u!); } }); var ninjy = new Ninja(JDD); ninjy.speak(); ninjy.kick(); Dmitry. That is, it's not actually the main issue, we normally can write in ES3/5 code something like this: var Foo = Class({ constructor: function (a) { this.a = a; }, activate: function () { return this.a; } }); var Bar = Class({ constructor: function (a, b) { this.super(a); this.b = b; }, activate: function () { console.log(this.b + this.super()); } }); var bar = new Bar(10, 20); bar.activate(); // 30! P.S.: of course this.super() is much more convenient than (real code from e.g. ExtJS) `Bar.superclass.constructor.apply(this, arguments)` (what? are you kidding me, guys? Seems you just like syntactic noise). But unfortunately because of hack-nature (`caller` is not-standard and banned, people afraid to augment `Object.prototype`, wrappers are not so efficient), so it's not e.g. for cross-browser code. Though, I was pleased to use it in my library in the project where I had SpiderMonkey-only stuff (patched Thunderbird), so there I used that `this.super` actively (OK, actually `this._super`, because only since ES5 we can use keywords as properties). However, regardless that we _can_ implement convinient and sugared super calls as a library, classes from the box will be more convenient IMO. Dmitry. /be Thanks -- Irakli Gozalishvili Web: http://www.jeditoolkit.com/ Address: 29 Rue Saint-Georges, 75009 Paris, France http://goo.gl/maps/3CHu On Tuesday, 2011-05-24 at 24:48 , Brendan Eich wrote: On May 23, 2011, at 11:25 AM, Bob Nystrom wrote: One thing I'd like the proposal to support, which it doesn't currently, is initializers on instance property declarations. Then you could do: class C { public _list = []; } With that, you'll correctly get a new _list on each instance of C when it's created. But (we've argued, I forget where so repeating it here), this looks like [] is evaluated once when the class declaration is evaluated. That is not what you intend. Then at some point (in the last thread on this) I remembered parameter default values, but they cover only missing parameters to the constructor. This _list member could be private. But it has to be initialized in a body that executes once per instantiation, which is not the class body -- it's the constructor body. /be ___ es-discuss mailing list es-discuss@mozilla.org mailto:es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org mailto:es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: The other constructors: Object.create() and String.fromCharCode()
On 05.06.2011 22:00, Peter Michaux wrote: ES has new Constructor() as its basic syntax for construction. This means that if other constructors are also beneficial that the syntax to call them is inconsistent. For example, ES3 had the String.fromCharCode and ES5 added Object.create. This is a basic idea of class-factory-methods, i.e. when an instance is created not directly by specified arguments, but with prior actions applied on the different kind of argument(s) passed to the factory. That is (pseudo-code): class Point new: (x, y) - this.x = x this.y = y end Point.fromString(s) = - Point.new(...s.split(:)) end a = Point.new(1, 2) b = Point.fromString(1:2) and this kind of methods are placed on constructors (the main idea which I'm saying, is that `String.fromCharCode` isn't here because of inconsistency, but because of it's such a class-method, which is constructor of an instance). These are both constructors of sorts. Would it be possible to add String.new etc so that construction is consistent? Sure, I also used such a notation with `.new` in my experiments. BTW, this is the approach used in Ruby too -- `new` is just (class-) method there. Unfortunately Date.now, Date.parse, Date.UTC don't return Date objects as they would be elegant cases of being other constructors. Yes in order to get consistent syntax, host objects would need to implement the static new method. It can be done with a simple library though -- just wrappers for all kind of cases. (I remember the idea of being able to write String.new rather than having to write String['new'] was discussed in the past. I don't know if keywords as bare object keys are allowed in ECMAScript but it seems to work in Firefox.) Yes, it's possible per ES5. Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array comprehensions shorter syntax (?)
On 01.06.2011 3:06, Waldemar Horwat wrote: On 05/29/11 07:00, Dmitry A. Soshnikov wrote: Yeah, and ES also supports them. It's called a generator expression; in this proposal it would look like: let squares = (x * x | x data, x 5); Ahem, that's already a parenthesized comma expression with operands Yes, true (haha, this one is even a correct ES3 expression :D, and not only with the typo ` data`, but with the arrow: `- data`). Though, I just was excited with arrow functions so proposed Erlang's list comprehensions (Erlang also uses arrows for functions btw, though, that's said, it uses two pipes [X*X || X - Data, X 5]). Regarding comma, I though, perhaps it would be possible to treat it correctly in this context -- well, no means no. P.S.: another question I have -- is it worth and makes sense to raise a topic on considering/standardizing the pattern matching (Dave's proposal)? http://wiki.ecmascript.org/doku.php?id=strawman:pattern_matching Brendan mentioned on Twitter that it's too late (?), but IMO this proposal is much more interesting and needed for the lang than e.g. WeakMaps (which of course are also useful stuff, but not so powerful addition as pattern-matching would). Dmitry. x * x | x data and x 5. Remember that | is a perfectly fine binary operator. Waldemar PS. Block lambdas don't suffer from this problem because neither | nor || is a valid unary prefix operator, so they can be made syntactically unambiguous. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array comprehensions shorter syntax (?)
On 01.06.2011 10:57, David Herman wrote: P.S.: another question I have -- is it worth and makes sense to raise a topic on considering/standardizing the pattern matching (Dave's proposal)? http://wiki.ecmascript.org/doku.php?id=strawman:pattern_matching Brendan mentioned on Twitter that it's too late (?), but IMO this proposal is much more interesting and needed for the lang than e.g. WeakMaps (which of course are also useful stuff, but not so powerful addition as pattern-matching would). Not really. I want to see a pattern matching form for JS as much as anyone (and I did propose it) but it hasn't had enough time to get refined and promoted to the next stage. I only first proposed it a couple months ago, so it needs more time to mature. I understand, and actually I mentioned/proposed them here also an year ago and said that it would be great to have p-matching in JS. We have a very large set of features in official Harmony status for ES.next, and we are now beginning the refinement phase -- the meeting last week was the cutoff for proposals to get promoted to Harmony status. But don't despair! We aren't going to stop working on the next round of proposals. We'll keep the pipeline full with strawmen for ES.next.next even as we refine the ES.next proposals. As Brendan said at the last meeting, TC39 is superscalar. ;-) Yeah, glad to hear it. And BTW, comparing apples and oranges like pattern matching and weak maps is not really meaningful. In fact, if either one is more powerful it's weak maps; there's no way to simulate them in ES5, whereas pattern matching is just syntactic convenience... albeit totally awesome convenience. :) Ah, come on, of course I didn't compare them apples-to-apples. Just said that it's more likely that some elegant and powerful syntactic construction/sugar will be used more often than use-cases with WeakMaps and it turns out that much more time is given to WeakMaps than to p-matching. Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Array comprehensions shorter syntax (?)
Hi, Don't get this proposal as a bikesheding, just an idea in case if arrow functions will win the block-functions. What about to make a sugar for Array comprehensions based also on arrow syntax? The same as in Erlang: let data = [1, 2, 3, 4, 5]; let squares = [x * x | x - data, x 3]; // [16, 25] Which basically is the: let squares = [x * x for (x in values(data)) if (x 3)]; // [16, 25] A semantic (important) difference is that in the later case we use values(...) generator function to get the values. In case of shorter syntax, the array is assumed to be traversed over values by default. P.S.: 1. This syntactic construct is directly reflects the sets builder from set theory (http://en.wikipedia.org/wiki/Set-builder_notation), which again directly reflects arrays comprehensions concept: S = { 2 · x | x N } 2. Erlang actually uses two pipes, in this proposal I think one pipe is enough (like in Haskel IIRC): Erlang: Squares = [X * X || X - Data, X 3]; 3. Of course it's assumed that we can destructure elements in such array comprehensions: let users = [ {name: Alex, age: 31}, {name: John, age: 25}, {name: Mark, age: 33} ]; let names = [name | {name, age} - users, age 30]; // [Alex, Mark] 3.1. ...which can lead to real pattern-matching Dave's proposal to be included ;) switch-on-steroids is very powerful thing. Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array comprehensions shorter syntax (?)
On 29.05.2011 16:18, Jose Antonio Perez wrote: 2011/5/29 Dmitry A. Soshnikov dmitry.soshni...@gmail.com mailto:dmitry.soshni...@gmail.com Hi, Don't get this proposal as a bikesheding, just an idea in case if arrow functions will win the block-functions. What about to make a sugar for Array comprehensions based also on arrow syntax? The same as in Erlang: let data = [1, 2, 3, 4, 5]; let squares = [x * x | x - data, x 3]; // [16, 25] Basically you are proposing bring in Haskell's syntax for comprehensions Yeah, here I found a list of other syntax, including math root from sets theory: http://en.wikipedia.org/wiki/List_comprehension And taking into account to accept arrow functions, I think this Erlang's/Haskell's - notation fits nice and avoids the long for-loop and if-statement constructions. Besides, the ability to traverse directly over values without specifying it explicitly via generator IMO is also a good thing. 3. Of course it's assumed that we can destructure elements in such array comprehensions: let users = [ {name: Alex, age: 31}, {name: John, age: 25}, {name: Mark, age: 33} ]; let names = [name | {name, age} - users, age 30]; // [Alex, Mark] This form of located flat pattern matching is good. It should follow from the shorter notation of destructuring, and yeah, I also think it's good. Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array comprehensions shorter syntax (?)
On 29.05.2011 17:45, François REMY wrote: An alternative syntax, which I tend to prefer, is a LINQ-like syntax. As I noted from the beginning I wouldn't like to turn the topic into bikesheding with all possible syntax constructions for comprehensions (once again, there many interesting in many languages: http://en.wikipedia.org/wiki/List_comprehension); the idea was to adopt arrow symbol for that and only if arrow functions will be accepted. And the main thing is to write it shorted, after all we already have normal powerful list comprehensions borrowed from Python. Please note that LINQ don’t produce an array, but an enumerable. It means that if the result is never used, the query is never executed (and if only the first result is used, the query only executed itself to that point, and not further) let users = [ ] let names = ( foreach user in users select user.name if user.age 30 ); let newClientsSpendings = ( foreach user in users let spendings = getSpendingsById(user.id) select spendings if (user.isNewClient spendings.length!=0) ).merge() Yeah, and ES also supports them. It's called a generator expression; in this proposal it would look like: let squares = (x * x | x data, x 5); i.e. parens instead of brackets. In this way we create a generator object and behind the scene call its `next` method. But I don’t know if we really need something special (ie: a new syntax) for that kind of things. Using a short function notation + paren-free loops could do the trick pretty well : Perhaps, I don't cancel it. Let's see: // full notation let squares = [x * x for (x in values(data)) if (x 5)] // paren-free let squares = [x * x for x in values(data) if x 5] // set-builder notation let squares = [x * x | x - data, x 5 ] Yes, I like paren-free notation as well. So, it's really just a proposal, it can be accepted or not, depending on needs and complexity of implementation. Moreover, it's syntactically incomparable. let newClientsSpendings = @{ foreach user in users { if !user.isNewClient: continue; let spendings = getSpendingsById(user.id); if spendings.length!=0: yield spendings; } }().merge(); For your “squares” sample, that gives : let squares = @{ foreach x in data { if x3 : yield x*x } }(); It’s longer, That's it, exactly. We always looking for a shorter sugar. Though, the main thing that the sugar shouldn't be cryptic at the same time. Probably Erlang's list comprehensions are cryptic for someone, but again, taking into account arrow-functions, seems arrow-comprehensions aren't so cryptic. but it’s aslo more extensible... and it don’t introduce anything new to ES Harmony. As well as current array-comprehensions; though, paren-free are better IMO. Dmitry. Please note that your syntax has to be rejected because we can’t get intellisense working since the variable is declared after the expression. Best regards, François *From:* Jose Antonio Perez mailto:josea...@gmail.com *Sent:* Sunday, May 29, 2011 2:18 PM *To:* es-discuss@mozilla.org mailto:es-discuss@mozilla.org *Subject:* Re: Array comprehensions shorter syntax (?) 2011/5/29 Dmitry A. Soshnikov dmitry.soshni...@gmail.com mailto:dmitry.soshni...@gmail.com Hi, Don't get this proposal as a bikesheding, just an idea in case if arrow functions will win the block-functions. What about to make a sugar for Array comprehensions based also on arrow syntax? The same as in Erlang: let data = [1, 2, 3, 4, 5]; let squares = [x * x | x - data, x 3]; // [16, 25] Basically you are proposing bring in Haskell's syntax for comprehensions 3. Of course it's assumed that we can destructure elements in such array comprehensions: let users = [ {name: Alex, age: 31}, {name: John, age: 25}, {name: Mark, age: 33} ]; let names = [name | {name, age} - users, age 30]; // [Alex, Mark] This form of located flat pattern matching is good. Jose. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array comprehensions shorter syntax (?)
On 29.05.2011 23:29, Brendan Eich wrote: On May 29, 2011, at 7:17 AM, Jose Antonio Perez wrote: 2011/5/29 Dmitry A. Soshnikov dmitry.soshni...@gmail.com mailto:dmitry.soshni...@gmail.com That's it, exactly. We always looking for a shorter sugar. Though, the main thing that the sugar shouldn't be cryptic at the same time. Probably Erlang's list comprehensions are cryptic for someone, but again, taking into account arrow-functions, seems arrow-comprehensions aren't so cryptic. I think that your proposal based in Haskell's syntax is natural,clear and easy for the user. A EBNF grammar for it: ListComprehension : '[' Expression '|' IterableOrFilter (,IterableOrFilter)+ ']' IterableOrFilter: Id '-' ArrayOrGenerator | BooleanFilter The problem is the LL(1) conflict with Array Literal, but that doesn't matter much, right? ;) No, it's a big incompatibility that could result in no early error, rather a shift in meaning. We're not doing those without a really good reason. We don't have one here. OK; it has been just proposed. Basically I think paren-free for-in + if scheme is fine, just though it can be more sugared with the arrow. But, there's no a _big_ need, I agree. P.S.: though, btw, IIRC, you said the same when an year ago I proposed arrow functions or Ruby's blocks and they were refused because of grammar reasons; today we want them to standardize ;) I mean, perhaps what seems not so needed and complicated to implement at first glace, later can become interesting and useful. Dmitry. People seem to forget that | is an operator in the language. In http://wiki.ecmascript.org/doku.php?id=strawman:block_lambda_revival I worked around the lesser problem of parameter default values by requiring any default value using bitwise-or to be parenthesized: blam = {|x = (y | z)| x*x}; But block-lambdas do not use [] where | may be an operator in a single element initialiser expression, so there's no further incompatibility. Not so with square brackets. Array comprehensions using for-in or the replacement (paren-free, probably for-of) Harmony syntax are in for ES.next. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Is class syntax really necessary ?
On 23.05.2011 14:17, Irakli Gozalishvili wrote: Hi, I think there lot's of proposals for ES.next that require syntax extensions, which is probably worth if new functionality added or shortens most commonly used constructs like functions (were no other option is available). In case of this proposal: http://wiki.ecmascript.org/doku.php?id=strawman:classes_with_trait_composition#open_issues even though I like it I'm not sure adding new syntax is worth it. May I ask a counter question -- why do you think it's not good to add syntactic sugar for classes? It's a kind of a strange thing. People sometimes talk about unnecessarily of a sugar. But why I'm asking? Is it bad to use a sugar? Or do you _really_ worry about an _implementation_ that e.g. a language will be too heavy? After all, it's not even the issue of users, it's the issue of implementers. That is, since it's just a sugar, the users _still_ are free to use _desugared_ constructions (i.e. constructor + prototype + manual linkage of parent prototype in case of inheritance). If they want to. If they instead want to write with the sugar -- why we should worry about that adding of new syntax is worth (taking into account that `class`, `extends`, etc. keywords are already reserved since ES3 era). So from what I can tell, right after the sugar for classes is standardized, everyone will just start to use it and forget about desugared constructions. And nobody even will think and bother about whether it's worth or not. A good point of standardizing this wrapper (which is just a sugar) is that all ad-hoc class-wrappers of libraries will be just eliminated and there will be common classes sugar from the box. Since JS already supports classical inheritance (though, without sugar), I don't how it's bad not to standardize the sugar for it. It will be convenient who need to program a class-based system. At the same time, if someone will still need a chaotic code reuse, i.e. a prototype-based inheritance (reuse a code from that object from which I want) -- they still be able to use things as `Object.create` (or | operator, etc.) I'm not suggesting that sugar for class composition is not necessary, example from three.js https://github.com/mrdoob/three.js/blob/master/src/objects/SkinnedMesh.js used by proposal highlights necessity pretty very well, I'm just thinking of doing that without introducing new syntax, here is one option: https://gist.github.com/986487 This way syntax noise may be reduced in addition this can be shimmed into current JS by implementing `Function.prototype.extend`. Yeah, OTOH, it can be so too. Though, the _familiar_ sugar will be bring the ability to involve programmers quicker. Also every single frameworks today does something similar in one form or another, IMO all is necessary is to have a standard that will let bikeshedding go away. Right. Dmitry. I think there is also a good precedent of this with `Function.prototype.bind`. Here are some related links: http://documentcloud.github.com/backbone/ http://base2.googlecode.com/svn/version/1.0.2/doc/base2.html#/doc/!base2.Base http://prototypejs.org/learn/class-inheritance http://startdojo.com/2011/03/02/dojo-classes-inherited-and-constructors/ http://mootools.net/docs/core/Class/Class http://ejohn.org/blog/simple-javascript-inheritance/ Kind regards -- Irakli Gozalishvili Web: http://www.jeditoolkit.com/ Address: 29 Rue Saint-Georges, 75009 Paris, France http://goo.gl/maps/3CHu ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: prototype for operator proposal for review
Besides. The same inheriting keyword can be used for both -- classes inheriting and just classless (or chaotic, prototypal) reuse: foo bar class Foo Bar or foo extends bar { y: 20 } class Foo extends Bar Since both implements the same pattern -- linear vertical tower of code reuse (in simple words -- just single inheritance), then the same keyword seems also logical. Dmitry. On 18.05.2011 11:41, Dmitry A. Soshnikov wrote: On 18.05.2011 6:50, Allen Wirfs-Brock wrote: We had so much fun with feedback on my Unicode proposal I just have open another one up for list feed back: An updated version of the prototype for (formerly proto) operator proposal is at http://wiki.ecmascript.org/doku.php?id=strawman:proto_operator Just a small note on: There are many other possible special character alternates to *|||*. For example, *|||*, *|^^|*, *|*|*, *||*, *|^||*, *||-|*, etc. It isn't clear that any of these is more meaningful or mnemonic than *|||*. Perhaps just less than would be enough? Why we need two symbols? It's by the way, a real implementation of subclassing in Ruby: class Foo def alert p Called from Foo class end end class Bar Foo def alert super end end bar = Bar.new bar.alert # Called from Foo class It sounds quite logical -- by hierarchy Bar is *less than* Foo. And also: what's happened to meta-properties in initialisers? It seems to me that having them we get also the ability not only to specify the proto, but also other control attributes for properties and to the object. And since #-symbol has changed its semantics, and instead --functions (or probably Ruby's blocks) are on agenda instead, maybe we may use # exactly for meta properties? let foo = {x: 10}; let bar = { #proto: foo, #closed y: 20, // etc. }; Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
paren-free call expressions
Hi, Parens-free call expression allow to provide some actions /decoratively/. From this, the consequence of easy and elegant DSLs (domain specific languages). For example: class Account { attributes customer, cart } Thus, call to `attribute` function looks like not the imperative call, but like a declaration that instances of Account class has those attributes. Ruby uses exactly this approach of its attr_accessor, private, etc. keywords which in fact are just functions placed on the very basic class: class Foo attr_accessor :x, :y end foo = Foo.new foo.x = 10 foo.y = 20 which in fact is just a syntactic sugar (not at grammar, but at application level via simple `attr_accessor` function) for the: class Foo def x end def x=(value) end def y end def y=(value) end end That is, create getter and setter for every needed property (yes, in Ruby all public properties are accessors). Thus, this function does it behind the scene: attr_accessor(:x, :y), however being called /without/ parens, it elegantly looks like a declarative keyword. Another example as is said, `private` function which also without parens looks like an operator. Besides, If - will be accepted, in many cases (being passed as callback) they will much more elegantly look without parens of call expressions. So what do you think? If the idea is good, may it bring some problems with parsers and grammar? P.S.: some examples of declarative DSLs: https://github.com/jashkenas/coffee-script/wiki/%5BExtensibility%5D-Writing-DSLs Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: paren-free call expressions
On 18.05.2011 20:16, Brendan Eich wrote: I'm working on a block-as-better-function proposal, essentially an alternative to arrow-function-syntax even though unlike the latter, the former has new semantics. One of the insights from Allen and Mark, which is kind of obvious to Rubyists, is that blocks as lightweight functions usable for building control abstractions really need paren-free calls to be as light as in Smalltalk, therefore actually usable compared to writing loops or even old-fashioned function expressions. Yeah, right. Sure, block-lambdas are good as lighter functions too, but they're not enough, and the TCP wins were considered losses in that context. Sorry, TCP? What's that? This is because a function can escape from a downward flow and later be invoked, then attempt to return from the activation of its static parent function after that function's activation has been deallocated. Yeah, a casual bidirectional (up/down) closure. A block may not escape. Indeed Ruby's simplest downward-funarg block protocol involves caller passing a block via a paren-free call, and the receiving method not declaring the formal, rather just calling it via Ruby's yield. No escape. Just only if the receiving method doesn't define the block explicitly via the last -argument. It's exactly the explicit block which is transformed to the Proc-object, and already this object can be returned upward. Though, there's no much sense in it, since the block is created lexically in the caller context and all caller's bindings are already closured in it anyway (will it be returned back or not -- no matter). Anyway, I'm going to include paren-free call syntax in the block-lambda proposal, not factor it out. It probably could be, but it's not as simple as you show. In particular, foo = Foo.new in Harmony should continue to get the 'new' property from Foo and assign it to foo. It should not implicitly call Foo.new(). Oh, of course. The same as in CoffeeScript. It will be a simple property reading, not calling. In Coffee we have to used () for calling a function without parameters. However in Ruby as is said there are no simple properties, all public stuff are _only_ methods. `foo.bar` -- is calling a method. `foo.bar = 10` -- is calling the method `bar=`, it's actually exactly parens-free mode of foo.bar=(10). So in JS/Coffee I do not expect Foo.new behave as a method. But Foo.new {x: 10} -- yes, and it's very convenient for declarative DSL. P.S.: so in proposal it will look like: [1, 2, 3].map {|x| x * x} not like this: [1, 2, 3].map({|x| x * x}); right? (just asking to include to the following talk) Dmitry. On May 18, 2011, at 8:53 AM, Dmitry A. Soshnikov wrote: Hi, Parens-free call expression allow to provide some actions /decoratively/. From this, the consequence of easy and elegant DSLs (domain specific languages). For example: class Account { attributes customer, cart } Thus, call to `attribute` function looks like not the imperative call, but like a declaration that instances of Account class has those attributes. Ruby uses exactly this approach of its attr_accessor, private, etc. keywords which in fact are just functions placed on the very basic class: class Foo attr_accessor :x, :y end foo = Foo.new foo.x = 10 foo.y = 20 which in fact is just a syntactic sugar (not at grammar, but at application level via simple `attr_accessor` function) for the: class Foo def x end def x=(value) end def y end def y=(value) end end That is, create getter and setter for every needed property (yes, in Ruby all public properties are accessors). Thus, this function does it behind the scene: attr_accessor(:x, :y), however being called /without/ parens, it elegantly looks like a declarative keyword. Another example as is said, `private` function which also without parens looks like an operator. Besides, If - will be accepted, in many cases (being passed as callback) they will much more elegantly look without parens of call expressions. So what do you think? If the idea is good, may it bring some problems with parsers and grammar? P.S.: some examples of declarative DSLs: https://github.com/jashkenas/coffee-script/wiki/%5BExtensibility%5D-Writing-DSLs Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org mailto:es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: I noted some open issues on Classes with Trait Composition
On 16.05.2011 10:49, Brendan Eich wrote: On May 15, 2011, at 10:01 PM, Brendan Eich wrote: http://wiki.ecmascript.org/doku.php?id=strawman:classes_with_trait_composition#open_issues This looks pretty good at a glance, but it's a /lot/, and it's new. Looking closer, I have to say something non-nit-picky that looks bad and smells like committee: http://wiki.ecmascript.org/doku.php?id=strawman:classes_with_trait_composition#inheritance Two kinds of inheritance, depending on the dynamic type of the result of evaluating the //MemberExpression// on the right of ''extends''? That will be confusing. Is the traits-composition way really needed in this proposal? If so, then please consider not abuse ''extends'' to mean ''compose'' depending on dynamic type of result of expression to its right. Some simple examples of all use-cases would are needed I think. Regarding `new` keyword for the constructor (aka initializer), after all, it als may be OK. E.g. Ruby uses `new` as exactly the method of a class -- Array.new, Object.new, etc. Though, `constructor` is also good yeah. Regarding two inheritance types, I think better to make nevertheless one inheritance type -- linear (by prototype chain). And to make additionally small reusable code units -- mixins or traits -- no matter. Thus, of course if they will also be delegation-based and not just copy-own-properties, then we automatically get a sort of multiple inheritance. So again, better to have something like this: class Bar extends Foo { includes Comparable } where Comparable is a trait/mixin. It becomes an ancestor of the instance (via some hidden-class), E.g.: let bar = Bar.new(...args) Then we have the following hierarchy: bar - HiddenClass - Foo | | Comparable I.e. beside the vertical (tower) inheritance at each link of a chain we also have horizontal inheritance via mixins. Thus HiddenClass before going to its prototype chain, first try to find the property in the horizontal chain, i.e. in Comparable. A simple object may also mix some functionality without using a class (if a user still needs pure prototype-based code reuse): let bar = Object.mixing(Object.create(foo), Comparable); Delegation-based mixins though can be implemented as a library using proxies (example: https://github.com/DmitrySoshnikov/es-laboratory/blob/master/examples/mixin.js, implementation: https://github.com/DmitrySoshnikov/es-laboratory/blob/master/src/mixin.js, notice I also used Object.new :)). So we may actually understand what's going on by looking at the grammar, but nevertheless, if it's not hard, some simple examples would be nice. Besides, I restore my previous syntactic proposal (Coffee/Ruby-like again) with a simple rule: (1) `this` evaluated in the class body is the class, (2) `this` evaluated in the instance method body is the instance. These two rules seems quite simple, not-overheaded, and the class definition looks like as an object initialiser. I used @ as a sugar, though it's not essential currently. Also, notice, I used `initialize` for `new` or `constructor`, since it seems more exactly describes the essence of the method: http://dmitrysoshnikov.com/scheme-on-coffee/class.html Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: I noted some open issues on Classes with Trait Composition
On 16.05.2011 19:02, Brendan Eich wrote: On May 16, 2011, at 4:54 AM, Dmitry A. Soshnikov wrote: On 16.05.2011 10:49, Brendan Eich wrote: On May 15, 2011, at 10:01 PM, Brendan Eich wrote: http://wiki.ecmascript.org/doku.php?id=strawman:classes_with_trait_composition#open_issues This looks pretty good at a glance, but it's a /lot/, and it's new. Looking closer, I have to say something non-nit-picky that looks bad and smells like committee: http://wiki.ecmascript.org/doku.php?id=strawman:classes_with_trait_composition#inheritance Two kinds of inheritance, depending on the dynamic type of the result of evaluating the //MemberExpression// on the right of ''extends''? That will be confusing. Is the traits-composition way really needed in this proposal? If so, then please consider not abuse ''extends'' to mean ''compose'' depending on dynamic type of result of expression to its right. Some simple examples of all use-cases would are needed I think. Regarding `new` keyword for the constructor (aka initializer), after all, it als may be OK. E.g. Ruby uses `new` as exactly the method of a class -- Array.new, Object.new, etc. Though, `constructor` is also good yeah. My point is not to bikeshed, rather (a) to name existing prototype properties minimally, (b) to avoid preempting other names. Good, bad, or in between, the prototypal pattern in JS for constructor C binds C.prototype.constructorr to C. It does not bind C.prototype.new. Yeah, agreed. Regarding two inheritance types, I think better to make nevertheless one inheritance type -- linear (by prototype chain). And to make additionally small reusable code units -- mixins or traits -- no matter. Thus, of course if they will also be delegation-based and not just copy-own-properties, then we automatically get a sort of multiple inheritance. Self has multiple prototypes and you can use them for all kinds of inheritance patterns. Parents are Shared Parts... http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.28.1447rep=rep1type=pdf Organizing programs without classes http://citeseer.ist.psu.edu/viewdoc/download;jsessionid=77703261C2A470793139A1F79D8467AC?doi=10.1.1.127.5320rep=rep1type=pdf Yes, I've heard about Self'ish multi-protos but don't know the lang, though have heard that JS has taken some things from it. Thanks for the paper. Delegation-based mixins though can be implemented as a library using proxies (example: https://github.com/DmitrySoshnikov/es-laboratory/blob/master/examples/mixin.js, implementation: https://github.com/DmitrySoshnikov/es-laboratory/blob/master/src/mixin.js, notice I also used Object.new :)). Proxies are too costly, though. They always have a handler full of traps. Yep, it was just an example. The idea with classes is to capture prototypal inheritance as used today. Yeah, classes are just a sugar in this case, the same as in Coffee, the same as in Python. The idea with traits is to make composition flexible, with fast failure on conflict and tools to rename around conflicts. Yes, but IMO the most interesting for programmers the ability to mix reusable code. The conflict-resolver is derived. And if to implement this conflict-resolve traits will have to be just things for static augmentation of objects with own properties, I think I choose better just mixins. Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: arrow syntax unnecessary and the idea that function is too long
On 15.05.2011 10:33, Brendan Eich wrote: On May 13, 2011, at 11:25 PM, Brendan Eich wrote: I'll update http://wiki.ecmascript.org/doku.php?id=strawman:arrow_function_syntax to include an ES5 grammar patch. Done: http://wiki.ecmascript.org/doku.php?id=strawman:arrow_function_syntax, specifically http://wiki.ecmascript.org/doku.php?id=strawman:arrow_function_syntax#grammar_changes This requires splitting the sub-grammar starting at Expression (comma expression), at AssignmentExpression (which occurs in all comma-separated list non-comma-expression contexts, namely argument lists and initialisers), creating a parallel production chain from Statement through AssignmentStatement. Many languages restrict assignment to statement form. We don't need to do that and shouldn't break extant code that nests assignment expressions, but separating assignment statements (comma-separated lists of assignments) enables better right-hand side syntax for arrow function expressions -- namely, they don't have to be parenthesized. Thus you can write array.map((elem) - elem * elem) let identity = (x) - x; thrice = (x) - 3 * x; without gratuitous parenthesization. Calling an arrow function expression requires parentheses on the outside, of course: alert((- paren me)()); Comments welcome, I haven't had time to formalize and test this but it looks like it will work. Cool! // Use # to freeze and join to nearest relevant closure function return_pure() { return #(a) - a * a; } let p = return_pure(), q = return_pure(); assert(p === q); So, ES3 joined-objects are back. Though, the question is in their [[Scope]] difference (i.e. can be they joined in the following case): let foo = (args...) - { return #(a) - args.map(a); }; foo(1, 2, 3)((x) - x * x); // [1, 4, 9] foo(5, 10)((x) - x * x); // [25, 10] Do both have the same (reflected) [[Scope]] to be joined? At first glance with named args, e.g. foo(a, b, c) yes, but what's with rest args? Other things seems fine. Dmitry. /be Grammar Changes Change all uses of /AssignmentExpression/ outside of the /Expression/ sub-grammar to /InitialExpression/: ElementList :// See 11.1.4 Elisionopt InitialExpression ElementList , Elisionopt InitialExpression ... PropertyAssignment : // See 11.1.5 PropertyName : InitialExpression ... ArgumentList : // See 11.2 InitialExpression ArgumentList , InitialExpression ... Initialiser :// See 12.2 = InitialExpression InitialiserNoIn :// See 12.2 = InitialExpressionNoIn Define /InitialExpression/ and /ArrowFunctionExpression/: InitialExpression : AssignmentExpression ArrowFunctionExpression ArrowFunctionExpression : FormalParametersOpt Arrow [lookahead ∉ {{}] InitialExpression FormalParametersOpt Arrow Block FormalParameters : ( FormalParameterListOpt ) Arrow : one of - or = Split assignment out of /ExpressionStatement/ into /AssignmentStatement/: Statement : Block VariableStatement EmptyStatement AssignmentStatement ExpressionStatement ... AssignmentStatement : [lookahead ∉ {{, function}] AssignmentList ; AssignmentList : Assignment AssignmentList , Assignment Assignment : LeftHandSideExpression = InitialExpression LeftHandSideExpression AssignmentOperator InitialExpression ExpressionStatement : [lookahead ∉ {{, function}] ConditionalExpression ; Finally, /PrimaryExpression/ produces a parenthesized /ArrowFunctionExpression/: PrimaryExpression : ... ( ArrowFunctionExpression ) ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: arrow syntax unnecessary and the idea that function is too long
On 15.05.2011 21:09, Brendan Eich wrote: On May 15, 2011, at 8:14 AM, Dmitry A. Soshnikov wrote: // Use # to freeze and join to nearest relevant closure function return_pure() { return #(a) - a * a; } let p = return_pure () , q = return_pure () ; assert (p === q); So, ES3 joined-objects are back. Though, the question is in their [[Scope]] difference (i.e. can be they joined in the following case): The join to nearest relevant closure words were meant to address this. Let's see (I made a few typo and syntax fixes): let foo = (...args) - { return #(a) - args.map(a); }; foo(1, 2, 3)((x) - x * x); // [1, 4, 9] foo(5, 10)((x) - x * x); // [25, 100] Do both have the same (reflected) [[Scope]] to be joined? The two foo calls have different unjoinable scope chains enclosing variables captured by the returned #(a) - args.map(a) function, specifically args. So that hash-frozen arrow-function cannot be joined into one identity. At first glance with named args, e.g. foo(a, b, c) yes, but what's with rest args? Named vs. rest doesn't matter, the question is lexical capture. The name |args| is from the outer (...args) - { return #(a) - args.map(a); } function. It is used in the inner arrow function. The location of this |args| parameter is what is actually captured in general. Oh, my misunderstanding then. Then I just incorrectly treated yours assert(p === q); I though here you try to show that the engine will handle the case with optimization and reuse (i.e. to join) the function object. However, it still not possible because of different scope chain, that exactly why I was asking. So you mean just lexical addressing of free variable? I.e. without dynamic scope chain lookup (that what Dave Herman confused recently with dynamic scope concept IIRC). However it's interesting -- if ES6 will have lexical addressing anyway (that is there will be no dynamic bindings -- no `eval`, no `with`, etc, -- just compile-time bindings), this means that this optimization will be done in any way, -- without needing of this #function in this case. Or am I mistaken again? Thanks for explanations btw. Dmitry. This is optimizable to copying the value at that location in many cases, including this one, but that doesn't change the fact that the location varies with each call to foo. So args' abstract location differs, and therefore its value may differ, each time the inner arrow-function is evaluated. So the # freezes it but it will not be joined with other evaluations of the same source form. However you implement closures, something has to vary each time the inner arrow is evaluated, to capture the correct args, [1, 2, 3] or [5, 10]. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: arrow syntax unnecessary and the idea that function is too long
Oh, and just a small note -- perhaps there's a sense to put a comment near each line to what result the expression evaluates in your examples, e.g. asset(p === q); // true (or false?) etc. Dmitry. On 15.05.2011 22:55, Dmitry A. Soshnikov wrote: On 15.05.2011 21:09, Brendan Eich wrote: On May 15, 2011, at 8:14 AM, Dmitry A. Soshnikov wrote: // Use # to freeze and join to nearest relevant closure function return_pure() { return #(a) - a * a; } let p = return_pure () , q = return_pure () ; assert (p === q); So, ES3 joined-objects are back. Though, the question is in their [[Scope]] difference (i.e. can be they joined in the following case): The join to nearest relevant closure words were meant to address this. Let's see (I made a few typo and syntax fixes): let foo = (...args) - { return #(a) - args.map(a); }; foo(1, 2, 3)((x) - x * x); // [1, 4, 9] foo(5, 10)((x) - x * x); // [25, 100] Do both have the same (reflected) [[Scope]] to be joined? The two foo calls have different unjoinable scope chains enclosing variables captured by the returned #(a) - args.map(a) function, specifically args. So that hash-frozen arrow-function cannot be joined into one identity. At first glance with named args, e.g. foo(a, b, c) yes, but what's with rest args? Named vs. rest doesn't matter, the question is lexical capture. The name |args| is from the outer (...args) - { return #(a) - args.map(a); } function. It is used in the inner arrow function. The location of this |args| parameter is what is actually captured in general. Oh, my misunderstanding then. Then I just incorrectly treated yours assert(p === q); I though here you try to show that the engine will handle the case with optimization and reuse (i.e. to join) the function object. However, it still not possible because of different scope chain, that exactly why I was asking. So you mean just lexical addressing of free variable? I.e. without dynamic scope chain lookup (that what Dave Herman confused recently with dynamic scope concept IIRC). However it's interesting -- if ES6 will have lexical addressing anyway (that is there will be no dynamic bindings -- no `eval`, no `with`, etc, -- just compile-time bindings), this means that this optimization will be done in any way, -- without needing of this #function in this case. Or am I mistaken again? Thanks for explanations btw. Dmitry. This is optimizable to copying the value at that location in many cases, including this one, but that doesn't change the fact that the location varies with each call to foo. So args' abstract location differs, and therefore its value may differ, each time the inner arrow-function is evaluated. So the # freezes it but it will not be joined with other evaluations of the same source form. However you implement closures, something has to vary each time the inner arrow is evaluated, to capture the correct args, [1, 2, 3] or [5, 10]. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: arrow syntax unnecessary and the idea that function is too long
On 16.05.2011 0:37, Brendan Eich wrote: On May 15, 2011, at 11:55 AM, Dmitry A. Soshnikov wrote: Oh, my misunderstanding then. Then I just incorrectly treated yours assert(p === q); This was from // Use # to freeze and join to nearest relevant closure function return_pure() { return #(a) - a * a; } let p = return_pure(), q = return_pure(); assert(p === q); and the assertion means what it seems: p is identical to q. I though here you try to show that the engine will handle the case with optimization and reuse (i.e. to join) the function object. I'm not talking about optimization -- this is a case where joining works, since the function is pure. It closes over no outer variables' locations. However, it still not possible because of different scope chain, that exactly why I was asking. No, that's not what the strawman says, and not what I said last time. The issue is not different scope chains, it is whether there are captured closure variables whose abstract locations are not invariant with respect to the source function expression in question. Each evaluation of a given function expression gives a fresh object in JS today. WIth joining as Mark proposed at http://wiki.ecmascript.org/doku.php?id=strawman:const_functions#joining Got it. Though it still seems to me as just an implementation optimization without need to specify explicitly that a function is closed (without free variables) and thus can be optimized, i.e. created once and stored as some internal property. Dmitry. and with opt-in syntax (the # prefix) as I'm proposing, this fresh function object for each evaluation of a function expression rule would no lot apply. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: arrow syntax unnecessary and the idea that function is too long
On 16.05.2011 0:40, Brendan Eich wrote: On May 15, 2011, at 11:56 AM, Dmitry A. Soshnikov wrote: Oh, and just a small note -- perhaps there's a sense to put a comment near each line to what result the expression evaluates in your examples, e.g. asset(p === q); // true (or false?) That is confusing and pointless. I meant what I wrote. The assertions are intended to claim that their argument conditions are truthy. Yeah, OTOH, yes. See last reply for more on joining. It occurs to me you thought scope chain varying in the context of a pure hash-rocket such as #-42 means that function cannot be joined, but since it is pure, it need not entrain its scope chain as an internal [[Scope]] property. More, since # freezes, there's no need for it to be duplicated, since there is no mutation side channel. So http://wiki.ecmascript.org/doku.php?id=strawman:arrow_function_syntax proposes freezing and joining, only if the user specifies via the # prefix. Yep, I got it, thanks, though, as mentioned seems it can be managed then at engine level without explicit specifying by the user, no? Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Function Syntax
On 13.05.2011 1:25, Brendan Eich wrote: On May 12, 2011, at 1:06 PM, Brendan Eich wrote: On May 12, 2011, at 10:55 AM, Brendan Eich wrote: Ruby is far from simple, btw. Check out http://samdanielson.com/2007/3/19/proc-new-vs-lambda-in-ruby and the wikipedia page it references. Looks like Proc.new but not lambda can return from its caller. From http://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Method_Calls it should be clear I was missing the block target. Blocks are syntactically restricted to being downward funargs. Only if reified as Procs do they potentially escape to be called later when their lexical parent method could have already returned. IOW, blocks are restricted to being downward-funargs by syntax at their expression site, and by default in the callee (without the before the corresponding formal parameter). To say a bit more about this, here's a demo of the downward-only-funarg nature of blocks passed as extra trailing arguments, with no matching parameters: def say puts yield world end def say_hello say {|x| hello #{x} } end say_hello The output is hello world of course, but Ruby's yield calls the block without it escaping as a reified Proc that could be invoked later, after the downward flow. Neat! (Rubyists, please correct anything wrong here.) If the block is described explicitly in the method definition (that is, the last parameter with ) then it can be returned back as a result: def foo block if block_given? yield 10 # call the block implicitly block.call 20 # the same, but explicitly block # return the block back end end # pass the block downwards, # and get it back (upwards) as a result returned_block = foo { |i| print i } # and call it again returned_block.call 30 Though, there's no much practical sense in this, since the block lexically is created in the global context of (in this case particular case) and captures its bindings, it, obviously isn't related with bindings of callee. Brendan, take a look at this detailed source-article explanation of closures in Ruby http://innig.net/software/ruby/closures-in-ruby.rb (it's executable file, so a good tutorial). There all this stuff with blocks, etc is explained well. P.S.: damn, it's so sorry that I haven't much time now to be involved deeply into the recent discussions of shorter function syntax. I hope I'll read carefully those threads later. A one thing I'd like to mention, we should not afraid of changes even if they syntactically aren't so familiar and habitual as were in Java. P.S.[2]: - syntax is / was long time before CoffeeScript. It's just a standard math definition of a function, it's used as a type of a function -- lambda abstraction -- in the lambda calculus, that is the arrow type. It's used in many other langs, e.g. Erlang (which I use in my current job), Haskell, other. So, don't afraid it. Though, the issues with hand-written LL parsers should be also considered. Dmitry. I'm not suggesting we copy any of this, just passing along my Ruby-n00b knowledge. When we considered lambdas (the Allen's lambda syntax proposal thread from late 2008 to early 2009), we did not try to confine them syntactically to actual parameter lists. Did we miss a key restriction or feature of Ruby? I'm not sure, I'm too much a Ruby n00b. If blocks could not escape to be called after their enclosing function had returned, then we would overcome the objection raised last time, articulated best by Maciej: https://mail.mozilla.org/pipermail/es-discuss/2008-December/008390.html But Ruby went all the way, allowing a block to grow into a Proc and outlive the method in which the block was expressed. I expect similar ecological pressures to apply if we added blocks only as downward-funargs. Plus, we'd still want shorter function syntax, not just blocks as downward-only funargs (however nice for map, forEach, etc.). I will write up a block strawman, to give it a fair shake along side http://wiki.ecmascript.org/doku.php?id=strawman:arrow_function_syntax. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Best practices for exception handling?
On 30.04.2011 0:22, Axel Rauschmayer wrote: Would it make sense to standardize more exception/error types, for example to add a MissingParameterError in ES.next? No proposal yet for demanding actual parameter count match formal, so this would not be used. Right. I would use it when I do my own checking. This idea is mainly motivated by Java having several predefined exceptions with descriptive names that are easy to reuse. With JavaScript, is throwing a string considered bad style (now or in the future)? That is, is throwing a new Error(msg) better than throwing msg directly? Why? In general when you don't need a complex structure of an exception to analyze, the ability to throw strings IMO is better than Java's long-long line of WhatAnNiceMidnightOn30OfAprilExceptionIn. Dmitry. Axel ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Automatic Semicolon Insertion: value vs cost; predictability and control; alternatives
On 17.04.2011 21:07, Garrett Smith wrote: On 4/17/11, Brendan Eichbren...@mozilla.com wrote: On Apr 17, 2011, at 10:52 AM, Claus Reinke wrote: [TLDR] ASI is not going to be removed. I don't know why you think it could be. Why not? Iif developers would stop doing that then eventually, can't it be removed? It is not hard at all to write code that does not rely on ASI. The question is not that it's hard or not. IMO an explicit semicolon is really a syntactic noise in the language. In goes to the early era of C/Pascal, etc. Since usually, a programmer puts a one logical sentences per line -- *for what* you need additional statement/expression termination besides the new line itself? The useless actions in this case can be compared with masochism. So it's a noise. But a completely different thing is the implementation of ASI and all subtle/tricky/buggy cases related with it which exactly causes dislike of the ASI. If the ASI had been implemented perfectly -- will you still continue to put this noise explicitly? Why? IMO, the semicolon should be inserted only when there is ambiguous syntactic construction, or, e.g. when you want to put more than one sentence in one line. It's like a grouping operator -- usually we use it when we need to solved the precedence conflict, we don't use it manually everywhere, because it's, obviously, noisy and useless. The same with this semicolon. If we need specify such a place -- we put it. If we need to prolong the statement to several lines -- use slash (or anything else) -- but these are rare cases. Personally I always used semicolon when was programming on JS, but -- only to support style guide accepted in the company. I think I wouldn't now, however, yeah, there're very subtle case because of current implementation of ASI exactly in JS which will cause the issues. So still I'd prefer to use semicolon in JS. However, I wouldn't in Coffee/Ruby of course. (Deprecated production: missing semicolon, line 29). It's seems to me as an old era of typing-lovers. The machine should know where I *assume* the ending of a statement. It's not me who should do this dirty job every line! But when the machine is not smart enough, I can help it by placing the semicolon explicitly and these should be rare cases. Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Existential operator
On 14.04.2011 23:40, Sam Tobin-Hochstadt wrote: On Thu, Apr 14, 2011 at 3:29 PM, Dmitry A. Soshnikov dmitry.soshni...@gmail.com wrote: But these globals won't be accessible to scripts that have already been compiled; only to scripts that are subsequently compiled and evaluated, e.g. via ModuleLoader.eval. Which again seems as in chaise of efficiency, let's take away (a little of) convenience from a user. This isn't about efficiency at all! The reason that Dave and I have worked hard to make modules lexically scoped, of which this is a part, is so that when you look at a program, you can understand what it does. This is a fundamental part of programming, and not having a clear binding structure in your language makes it much harder. Sometimes, this makes your program more efficient, too, because the compiler understands your program better for the same reasons that you can understand your program more easily. But that really isn't the point. Actually, ECMAScript is already lexically scoped language (in respect of closures). I think there's a mess with treating a possibility of creating a binding at runtime with the dynamic scope. Dynamic scope (http://bit.ly/hz7tT2 -- just for interested) is an early design flow in PLT backing to Lisp invention times (where language authors have no much experience). Perl e.g. still has both -- dynamic and static scopes. But JS has/had lexical scope. Yes, `with` and `eval` (direct, non-strict) _are_ the features which brings dynamics to the static scope of ES. And I always thought (and it seems quite logical) that the direct lexical mapping of ids (which is the reason of disallowing of creating of runtime bindings) is exactly to improve the identifier resolution and technically it's the main reason. Avoiding object to represent a scope and avoiding a scope chain consisting of these object is the reason of providing direct map of variable name : direct address which (theoretically?) is accessed in O(1). But, I think it's a kind of off-topic in this thread, though, feel free to talk on it (probably in PM) if there's a need ;) Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Existential operator
On 14.04.2011 23:48, David Herman wrote: Dynamic binding is bad, mmmkay? ;) Mmmkay, Mr. Mackey :P But the main reason is increasing of performance. Of course, the understanding of _your bindings_ (i.e. which vars are present in the program) is also the reason, but it seems manageable. Seriously, it's not an efficiency thing. Dynamic scope is easy to write but hard to predict. JS is lexically/statically scoped almost everywhere, except for with, eval, and the global object. Strict mode solves with and eval. Harmony solves the global object. Yeah. You said (in the next letter) that it will be a local (like the let- ones) binding. Seems, it will break previous semantics. No, it doesn't. The previous semantics doesn't include local functions. That's a non-standard extension. Yes, I know it's non-standard, but anyway the old code (at least with the most logical approach in SpiderMonkey if people used them) will be broken. But, let's hope a percentage of such uses is small, since, repeat, currently the best practice is to avoid them. Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Existential operator
On 15.04.2011 23:56, Sam Tobin-Hochstadt wrote: On Fri, Apr 15, 2011 at 3:40 PM, Dmitry A. Soshnikov dmitry.soshni...@gmail.com wrote: On 14.04.2011 23:40, Sam Tobin-Hochstadt wrote: On Thu, Apr 14, 2011 at 3:29 PM, Dmitry A. Soshnikov dmitry.soshni...@gmail.comwrote: But these globals won't be accessible to scripts that have already been compiled; only to scripts that are subsequently compiled and evaluated, e.g. via ModuleLoader.eval. Which again seems as in chaise of efficiency, let's take away (a little of) convenience from a user. This isn't about efficiency at all! The reason that Dave and I have worked hard to make modules lexically scoped, of which this is a part, is so that when you look at a program, you can understand what it does. This is a fundamental part of programming, and not having a clear binding structure in your language makes it much harder. Sometimes, this makes your program more efficient, too, because the compiler understands your program better for the same reasons that you can understand your program more easily. But that really isn't the point. Actually, ECMAScript is already lexically scoped language (in respect of closures). I think there's a mess with treating a possibility of creating a binding at runtime with the dynamic scope. Dynamic scope (http://bit.ly/hz7tT2 -- just for interested) is an early design flow in PLT backing to Lisp invention times (where language authors have no much experience). Perl e.g. still has both -- dynamic and static scopes. But JS has/had lexical scope. Yes, `with` and `eval` (direct, non-strict) _are_ the features which brings dynamics to the static scope of ES. And I always thought (and it seems quite logical) that the direct lexical mapping of ids (which is the reason of disallowing of creating of runtime bindings) is exactly to improve the identifier resolution and technically it's the main reason. Avoiding object to represent a scope and avoiding a scope chain consisting of these object is the reason of providing direct map of variable name : direct address which (theoretically?) is accessed in O(1). 1. The global object (which is what's originally under discussion here) also gives you dynamic scope for top-level variables. window.fooish = 7 7 fooish 7 OK, what I was saying is that you mixing the terminology calling as dynamic scope the runtime bindings. And I mentioned that the dynamic scope is when a binding is resolved in the respect to the _callee_, but not in respect of the _definition place_ (i.e. _lexical_ place in the source code). var foo = 10; function bar() { console.log(foo); } (function () { var foo = 20; bar(); // 10 in static scope, 20 in dynamic scope! })(); But I'm of course agree that avoiding of runtime bindings and allowing only of static bindngs (i.e. those names which directly are resolved at compile time and _therefore_ the direct map of their addresses can be built -- to avoid scope chain lookup) is good -- from both sides -- to make these errors as early and (as usually it is) O(1) bindings resolution approach without any scope chain lookup. 2. Again, the reason that Dave and I have worked hard to avoid holes in the lexical scoping of identifiers in modules is for programmers to understand programs -- not for efficiency at all. Yes, it's OK, I got it. I don't know what else to say to persuade you of this, but making identifier resolution fast is not the main reason. Oh, it's not required, I got it. And I also won't persuade you, but just suggest this resource http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-35.html#%_sec_5.5.6 (the whole book is also recommended to be read if not yet). Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Existential operator
On 16.04.2011 0:06, Brendan Eich wrote: On Apr 15, 2011, at 9:56 PM, Sam Tobin-Hochstadt wrote: 1. The global object (which is what's originally under discussion here) also gives you dynamic scope for top-level variables. Right -- this is important and it is a deoptimer for optimizing implementations, but they can cope. The real problem is for JS hackers who cannot be sure their foopey typo (when they meant foopy) won't resolve to something else, accidentally or maliciously. Sure, this is the issue, though this is already done (in strict mode) but as a runtime error; thus, dynamic bindings are kept (i.e it's possible to `this[foo + bar] = 10`). Direct lexical addressing taking way the ability of `this[foo + bar] = 10` provides those errors (of `nonExisting = 10`) to be compile-time error. That's it. But the issue which Sam and you mention is already solved. So that's why I said that the most important is the ability of the fast lookup. 2. Again, the reason that Dave and I have worked hard to avoid holes in the lexical scoping of identifiers in modules is for programmers to understand programs -- not for efficiency at all. I don't know what else to say to persuade you of this, but making identifier resolution fast is not the main reason. Well, you've said it, that's enough on its face ;-). Developers I talk to really want early error on typos, it's a no-brainer. Right. Dmitry, if you mean something other than revoking this win of Harmony lexical scoping, please correct me. Otherwise, I do not see any good in reinjecting the global object (directly or via some kind of proxy) onto the scope chain. Nope, everything's fine and correct, I just was thinking (from what it's all started) that we'll not be able to expressively define some bindings directly in runtime depending on the condition, etc (as was shown in reply to David with isString, isArray, etc functions). And then we switch to the what's the main reason?. But of course to have all those errors as compile-time is a good improvement. And! Which allows to really optimize identifiers resolution (which IMO, ok, -- if not the first for you, but the one of the most important reasons of such an optimization) :P Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Existential operator
On 16.04.2011 0:59, Sam Tobin-Hochstadt wrote: On Fri, Apr 15, 2011 at 4:53 PM, Mark S. Millererig...@google.com wrote: I understand how dynamic scope works. And ES5 with the mutable global object has it: function bar() { return foo }; bar() // error: foo is not defined var foo = 7; bar(); // produces 7 Lexical scope would produce the error both times. Hi Sam, this does establish that ES5 does not have lexical scope. But I don't how ES5 has dynamic scope. In the above example, the 'foo' that bar has in scope during the second call still has nothing to do with what's in scope at the call site from which bar is called. I think what you're saying is that if I then do: (function (){ var foo = 8; return bar(); })(); I'll get 7, not 8, which is certainly true. We can think of this as dynamically scoped with respect to top-level variables, ie those bound at the top level or unbound at the time of definition, or we can think of this as a variety of scoping that is neither lexical nor dynamic -- that's just a terminology question. A runtime scope augmentation which still keeps the lexical scope (of functions in particular and mainly). But, yeah, I agree that we go into terminology discussion which is not the best. Let's agree on this: of course lexical bindings addressing is the best in respect of (a) optimized identifiers lookup and (b) having these errors as compile-time, not runtime, but (2) we lose the ability to expressively define some bindings. Is this approach correct now? ;) Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Existential operator
On 16.04.2011 0:45, Sam Tobin-Hochstadt wrote: On Fri, Apr 15, 2011 at 4:32 PM, Dmitry A. Soshnikov dmitry.soshni...@gmail.com wrote: OK, what I was saying is that you mixing the terminology calling as dynamic scope the runtime bindings. And I mentioned that the dynamic scope is when a binding is resolved in the respect to the _callee_, but not in respect of the _definition place_ (i.e. _lexical_ place in the source code). var foo = 10; function bar() { console.log(foo); } (function () { var foo = 20; bar(); // 10 in static scope, 20 in dynamic scope! })(); I understand how dynamic scope works. And ES5 with the mutable global object has it: function bar() { return foo }; bar() // error: foo is not defined var foo = 7; bar(); // produces 7 Lexical scope would produce the error both times. Just a small nit-picking: (1) you shouldn't use `var`, (2) lexical addressing will produce the only compile-time error on foo is not defined (since you write it as just `foo = 7`). But I'm of course agree that avoiding of runtime bindings and allowing only of static bindngs (i.e. those names which directly are resolved at compile time and _therefore_ the direct map of their addresses can be built -- to avoid scope chain lookup) is good -- from both sides -- to make these errors as early and (as usually it is) O(1) bindings resolution approach without any scope chain lookup. 2. Again, the reason that Dave and I have worked hard to avoid holes in the lexical scoping of identifiers in modules is for programmers to understand programs -- not for efficiency at all. Yes, it's OK, I got it. I don't know what else to say to persuade you of this, but making identifier resolution fast is not the main reason. Oh, it's not required, I got it. And I also won't persuade you, but just suggest this resource http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-35.html#%_sec_5.5.6 (the whole book is also recommended to be read if not yet). I first read SICP a long time ago :) Well, then you should know that the mentioned above chapter from the book is exactly about what I was saying, i.e., again -- let's make lexical addressing to make fast lookup. Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Existential operator
On 16.04.2011 1:17, Sam Tobin-Hochstadt wrote: On Fri, Apr 15, 2011 at 5:10 PM, Dmitry A. Soshnikov dmitry.soshni...@gmail.com wrote: I don't know what else to say to persuade you of this, but making identifier resolution fast is not the main reason. Oh, it's not required, I got it. And I also won't persuade you, but just suggest this resource http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-35.html#%_sec_5.5.6 (the whole book is also recommended to be read if not yet). I first read SICP a long time ago :) Well, then you should know that the mentioned above chapter from the book is exactly about what I was saying, i.e., again -- let's make lexical addressing to make fast lookup. 1. Just because I've studied SICP doesn't mean I agree with everything they say there. 2. The point of that section is describing an optimization that is possible, given lexical scope. They are certainly not advocating for lexical scope because it enables the optimization. OK, let it be. P.S.: so having this issue as already solved (as a runtime error, but still -- the error!, not a typo-hazard!) made me think that the main reason was another (as it's usually follows from having lexical addressing). OK, I propose to conclude at this point since we've found out the reasons. Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: harmony:modules with require
On 14.04.2011 11:38, Irakli Gozalishvili wrote: Hi, I just noticed that harmony modules have a different spelling then it used to have: module YUI ='http://developer.yahoo.com/modules/yui3.js'; module YUI = require('http://developer.yahoo.com/modules/yui3.js'); I wanted to know what was a reason for such a change. I am also concerned that this will bring quite a confusion as `require` is pretty well adopted function this days while spelling of it's modules is pretty much different. Agreed on breaking the web for the require name which already actively used today. Though, this name is used mostly exactly for the reason it's planned -- e.g. in CommonJS (and similar) for loading modules. However, we shouldn't exclude that the require can already be used for many other things which will break them (if not, why did we cancel fun and fn in respect of # for short functions notations? -- IIRC, exactly the reason fun / fn can already be used as normal identifiers. The same with require). I also raised recently this question (moreover, Dave (and me in my future presentation) used in his ES.next talk exactly first approach, without require). The answer was -- to support things such as: import (require ./modules/widgets.js).{Panel, Window} and that string literal is ambiguous with assignment a string to a module, which IMO not a sound reason at all. So I also think that just string literal is enough, and it won't break the web in respect of require identifier. Moreover, this looks for me absolutely OK and even more convenient: import ./modules/widgets.js.{Panel, Window} P.S.: other variants which I proposed for such a loading: import {Panel, Window} ./modules/widgets.js though, from keyword is asking to be included: import {Panel, Window} from ./modules/widgets.js Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Existential operator
On 13.04.2011 23:06, David Herman wrote: It'll be the WindowProxy as usual, in top level code. Dave has addressed what it will be in a module recently. I have to look on Dave's explanation, seems I missed it. But this WindowProxy won't be assessable then, right? Will it be possible to define a new global property/variable at all at runtime depending on condition? I think what Brendan means is that legacy script (that doesn't opt in to the new version) will continue to be ES5 and will continue to use the window object as the global scope frame. But the window won't be the global environment record in Harmony. In Harmony (as you know, Dmitry), the global scope is separate from the window object. At Harmony top-level, |this| is bound to an object that reflects the global scope, but it's not possible to do things like delete bindings from it, and it's a separate object from the window object. Yeah, thanks for reminding, Dave. I quote it from the spec-draft (for others): The initial binding of |this| at program top-level is a prototype-less, non-extensible, non-configurable reflection of the global environment record. Programs can get and set the global bindings through this object, but cannot add or remove bindings. So this means, no function expressions depending on the condition? I.e.: this[foo] = isDebug ? function () { ... } : function () { ... } Or I guess, such cases will be replaced with function statements, right? if (isDebug) { function debug() { ... } } else { function debug() { ... } } However, no dynamic function creation anymore (and actually, any binding). I just remember nice snippets such as: ['Object', 'Array', 'String', 'Function', 'RegExp'].forEach(function (constructorName) { this['is' + constructorName] = function (object) { return Object.prototype.toString.call(object) == '[object ' + constructorName + ']'; }; }); which allowed me to create several test-function such as isString, isArray, etc. Nothing of this anymore in ES6, right? And another quote from there: The initial binding of |this| at module top-level is the module instance object for that module. Just wanted to correspond this with the recent class-definition discussion, when I also proposed that this-value evaluated in the class body -- is the class itself, which allows to define elegantly class/static methods. Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Optional : in ?: operator [was: Existential operator]
On 14.04.2011 1:23, David Herman wrote: I don't think this feature is worth all this discussion or time, which is why I haven't said very much. But I don't like the idea. Are you talking about Kyles proposal or about my initial? I remind, my initial proposal was exactly about ?. operator to avoid this noisy and completely useless: if (foo.bar) { if (foo.bar.baz) { if (typeof foo.bar.baz.quax == function) { foo.bar.baz.quax(value) } } } and to replace it with: foo.bar?.baz?.quax(value); we can adopt it only for property accessor, nor for a variable binding directly (which seems doesn't create ambiguity). I.e. only for: foo?.bar but not for: foo? Dmitry. It *is* ambiguous, in the sense that if you wrote the grammar in the natural way it would be an ambiguous grammar, so you have to rewrite the grammar in such a way as to force precedence rules to disambiguate. But more importantly, I don't believe it's an important enough case to be worth syntactic support for, especially since `undefined' isn't always the default value you want to use. And FWIW: Racket actually moved *away* from supporting one-armed `if' -- they disabled it somewhere around v4, I think -- because experience showed that the cases where it was useful were outnumbered by the cases where it caused accidental leakage of `undefined' values, which is the moral equivalent of a NullPointerException. Dave Firstly, that code has no *real* ambiguity, because operator precedence tells us how those implied () sets disambiguate it. Secondly, in my opinion, the visual ambiguity of it is not made any more burdensome (and is even perhaps SLIGHTLY *clearer*) by adding () sets to disambiguate where you want optional `:`, such as this example (same as above, but where `g` and `j` are omitted as placeholders for implied `undefined`): a ? b ? c : d ? (e ? f) : (h ? i) : k == a ? (b ? c : (d ? (e ? f : undefined) : (h ? i : undefined))) : k Moreover, this code wouldn't have any actual ambiguity even if you omitted those two sets of () in the original. It would still be a valid expression, with a different (but still unambiguous) interpretation: a ? b ? c : d ? e ? f : h ? i : k == a ? (b ? c : (d ? (e ? f : (h ? i : k)) : undefined)) : undefined Developers who chain/nest ?: together are already familiar with how and when they have to use () to disambiguate, and the rules for what happens when they don't, and it seems like exactly the same effort for them to do so if implied `: undefined` were something they wanted to/could leverage. In sum, this sounds like an argument against ? as infix operator (implied : undefined). I'm sorry, I'm lost by this statement. I don't understand on what basis you conclude that I just argued against the very thing I'm asking for. Can you elaborate at all? var opts = { doX: (someX 0 someX 10) ? someX , // leaving off the `: undefined` (or `: null` if you prefer) doY: (someY 0 someY 1) ? someY // ditto }; Sorry, I think this is a hazardous pattern. doX suggests a boolean value, How is doX = (someX 0 someX 10) ? someX more suggestive of a boolean value than is doX = (someX 0 someX 10) ? someX : undefined Or, put another way, how are either of them suggestive of a boolean value result? Unless you mean simply the name doX being suggestive of do or do not (probably a poor name choice for my example), I don't see how either code snippet itself implies a boolean value result. As far as I am concerned, they both clearly indicate selecting a value (type irrelevant) based on a boolean test. The implied part hides one of the variable choices, yes, but I don't see how that suggests an entirely different type of operation/result? but you want (number | undefined), a type union. I'm not sure if you're arguing against: a) the pattern of having an `undefined` value in a variable when unset, that otherwise stores numbers when it's set; OR b) the implied `: undefined` If (a), this was a long held pattern long before I ever wrote my first line of JavaScript. Moreover, it's far more common today on the greater web than any code I've ever written. I'd argue it's pretty close to a de facto pattern at this point, so I'm not sure what the point is in using that argument to contradict my request for an implied `: undefined`. Moreover, this code sample I gave is only one such example. If it irks you that much, I'm sure I could find other examples to illustrate. But, I'm not really sure how that helps or hinders the process. If (b), I'm not sure what the type union for set vs. unset has to do with the request for implied `: undefined`? These seem like different discussions altogether. It sounds like you're basically saying either that my idea is very niche and thus irrelevant to consider, or that the supporting reasoning behind the idea is flawed/bad code, and thus the idea is necessarily flawed/bad. Is it either, both,
Re: Optional : in ?: operator [was: Existential operator]
On 14.04.2011 18:32, Dmitry A. Soshnikov wrote: On 14.04.2011 1:23, David Herman wrote: I don't think this feature is worth all this discussion or time, which is why I haven't said very much. But I don't like the idea. Are you talking about Kyles proposal or about my initial? I remind, my initial proposal was exactly about ?. operator to avoid this noisy and completely useless: if (foo.bar) { if (foo.bar.baz) { if (typeof foo.bar.baz.quax == function) { foo.bar.baz.quax(value) } } } and to replace it with: foo.bar?.baz?.quax(value); Sorry, with foo.bar?.baz?.quax?(value) which requires to parse not only ?. for functions as you see. Though, if it won't go for all convenient cases such as simple foo? then probably it's not so important. foo? ? bar : baz // looks odd, but acceptable though Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Existential operator
On 14.04.2011 20:42, David Herman wrote: Think of it this way: dynamic binding no, dynamic assignment yes. Yes, I've already learned it testing modules. Though, should say that it will decrease the beauty JS definitions as runtime expressions. The price? -- interpreter efficiency of course (direct lexical scope mapping of bindings, O(1) for resolving) and early-compile-time errors. But as was said, languages first of all are for humans, not for machines, so in chaise of efficiency we shouldn't turn the language into less convenient for exactly programmers. But, it's just a side phylosopical note ;) Moreover, I also cannot say that dynamic bindings are so often case, so the efficiency of course matters. So this means, no function expressions depending on the condition? I.e.: this[foo] = isDebug ? function () { ... } : function () { ... } var foo = isDebug ? function() { ... } : function() { ... } Yeah, right, but not dynamic names anymore. Or I guess, such cases will be replaced with function statements, right? if (isDebug) { function debug() { ... } } else { function debug() { ... } } Sure, that would be fine too. You said (in the next letter) that it will be a local (like the let- ones) binding. Seems, it will break previous semantics. Though, again, today the best practice is to avoid function statements at all, because of difference in implementation; only SpiderMonkey has the sensible one IMO. And in SM's it's a outer scope binding, not the inner. However, no dynamic function creation anymore (and actually, any binding). Of course you can still do dynamic function creation. You just can't do dynamic binding. Yes, yes, but which decreases elegance of definitions but increases intermediate noise (though, maybe not so noise?). I just remember nice snippets such as: ['Object', 'Array', 'String', 'Function', 'RegExp'].forEach(function (constructorName) { this['is' + constructorName] = function (object) { return Object.prototype.toString.call(object) == '[object ' + constructorName + ']'; }; }); which allowed me to create several test-function such as isString, isArray, etc. Nothing of this anymore in ES6, right? For the most part, this will not be possible. You can do it in a phased way, by creating the globals dynamically via the module loader *before* evaluating the script that wants to use them. E.g.: ['Object', 'Array', 'String', 'Function', 'RegExp'].forEach(function(constructorName) { ModuleLoader.defineGlobal('is' + constructorName, function(object) { return Object.prototype.toString.call(object) == '[object ' + constructorName + ']'; }); }); Hm, `defineGlobal`? It's interesting. But these globals won't be accessible to scripts that have already been compiled; only to scripts that are subsequently compiled and evaluated, e.g. via ModuleLoader.eval. Which again seems as in chaise of efficiency, let's take away (a little of) convenience from a user. Anyway, thanks for clarifications, Dave. Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Existential operator
On 14.04.2011 22:00, Brendan Eich wrote: On Apr 14, 2011, at 7:43 PM, Asen Bozhilov wrote: It will solve the problem with the ambiguous syntax. There is no ambiguity problem with ? followed by . and then (with whitespace allowed, of course) an IdentifierName. We need the lookahead to an identifier-name starting-character to avoid this: var tolerance = big ?.1:.01; Damn, it's a mind-bender :D Really hard to get what's going on in this expression. It's a good for quiz; thanks for the example. More human-view version (for interested): var tolerance = big ? 0.1 : 0.01; So we can't simply maximum-munch '?.'. But ?. is doable with some care, and probably better spelling than - (which does not connote the conditionality as ? does). /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: [Harmony proxies] Discussion on the declarative object experiment
On 12.04.2011 20:41, David Bruant wrote: Hi, I'd like to share my experience on a recent experiment. First off, I'd like to apologize for the name; declarative object doesn't really capture it and may be confusing. Second of all, what I have created doesn't really solve any use case (I'll discuss it), but offers at most some syntactic sugar. Code can be found here : https://github.com/DavidBruant/DeclO One idea is to have an object o. This object can accept any property name (get trap only in my case). Accessing a property will generate an object on-the-fly which itself can accept any property name and generate an object, etc. At the end, the object can be used as a constructor to do something. Example: --- var a = new o.azerty.are.the.first.letters.of.my.keyboard(); var b = new o.David.Bruant.writes.JavaScript(); --- The point could be to build something based on the property names (stored in the propNames variable and added with the push l.8). Of course, a constructor taking a string array could be as useful. That's the reason why I said earlier it doesn't solve any use case. The syntax sugar is the only added value I can think of. The exact use of the string array is to be defined in the constructTrap function. The pattern is here. Yes, the pattern is interesting, though, really, which practical use-case will it have? Currently a one possible I see -- a query to database with building the query itself. Sort of: where .name(Dmitry) .surname(Soshnikov) .active(true) etc (though, it should be callable in contrast with yours implementation). But, it also arguable whether it's so useful. However, your letter made me think on proposing existential operator, which is a syntactic sugar to avoid long testing whether a property exists and only after that to apply it. This already is again used in CoffeeScript, so I'll show the examples: let street = user.address?.street which desugars e.g. into: street = (typeof user.address != undefined user.address != null) ? user.address.street : undefined; The same with functions (which is even more convenient that just with properties): let value = entity.getBounds?().direction?.x which desugars into: let x = (typeof entity.getBounds == function) ? (typeof entity.getBounds().direction != undefined entity.getBounds().direction != null) ? entity.getBounds().direction.x : undefined undefined; (I specially avoid optimization with saving intermediate results -- just to keep clarity) I think it's useful thing and I already used in several times. Dmitry. Anyway, the main thing I want to share is a reflection on shared handlers. At l.13, all proxies created on-the-fly use the same handler object (I have purposefully not inlined it in l.10). Thinking about shared handlers, I have realized that a proxy internal state is stored in its method handlers and the way they interact with each other, so this has to be taken into account when considering sharing a handler among several proxies. In order to share the same handler, some proxies must share the same functions (even dynamically). Each function having a unique scope, it means that these proxies must share their traps scopes. So, either the state of several proxies is shared (like in my case where they share propNames on purpose) or the shared scope could be reduced to a WeakMap which in turn can store a per-instance state. Both solutions aren't mutually exclusive. David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: [Harmony proxies] Discussion on the declarative object experiment
On 13.04.2011 12:08, David Bruant wrote: Le 13/04/2011 09:02, Dmitry A. Soshnikov a écrit : On 12.04.2011 20:41, David Bruant wrote: Hi, I'd like to share my experience on a recent experiment. First off, I'd like to apologize for the name; declarative object doesn't really capture it and may be confusing. Second of all, what I have created doesn't really solve any use case (I'll discuss it), but offers at most some syntactic sugar. Code can be found here : https://github.com/DavidBruant/DeclO One idea is to have an object o. This object can accept any property name (get trap only in my case). Accessing a property will generate an object on-the-fly which itself can accept any property name and generate an object, etc. At the end, the object can be used as a constructor to do something. Example: --- var a = new o.azerty.are.the.first.letters.of.my.keyboard(); var b = new o.David.Bruant.writes.JavaScript(); --- The point could be to build something based on the property names (stored in the propNames variable and added with the push l.8). Of course, a constructor taking a string array could be as useful. That's the reason why I said earlier it doesn't solve any use case. The syntax sugar is the only added value I can think of. The exact use of the string array is to be defined in the constructTrap function. The pattern is here. Yes, the pattern is interesting, though, really, which practical use-case will it have? I warned from the beginning that I didn't see any :-p More seriously, the main point of sharing my experiment was the discussion on shared handlers for several proxies. Currently a one possible I see -- a query to database with building the query itself. Sort of: where .name(Dmitry) .surname(Soshnikov) .active(true) I have tried to think of a lot of use cases. This one, for instance, doesn't even requires proxies (As I understand it). As long as you know the number and names of the all properties (I assume you do by knowing which database table you're querying), ES5 accessor properties could be used. This goes with the restriction that it's likely to be far more memory consumming, but the pattern could be applied the same way. Now that I think about it, I realize that for getters/setters, the exact same object could be used (may depend on the use case). Same for my pattern, I use Proxy.createFunction for each intermediary (l.10), but I could factorize it and return the same proxy each time since traps don't change at all. Also, I'd like to note that if each of your property is a function call, you don't even need accessor properties. That's what jQuery already does by returning this. etc (though, it should be callable in contrast with yours implementation). But, it also arguable whether it's so useful. I have no strong opinion on callable or not. It was just an idea that the pattern would better be used as a constructor. The main point of the pattern lies on the use of the get trap in firstHandler and middleHandler. It could be improved by a different call/construct trap (and the use of arguments for these). Yeah, right, that's why I also mentioned that it's arguable whether the pattern is useful to apply to this particular issue. It wast just a guess. Regarding shared handlers, if exactly this is the point, we have also think which practical things can we have. However, your letter made me think on proposing existential operator, which is a syntactic sugar to avoid long testing whether a property exists and only after that to apply it. This already is again used in CoffeeScript, so I'll show the examples: let street = user.address?.street which desugars e.g. into: street = (typeof user.address != undefined user.address != null) ? user.address.street : undefined; Shouldn't it desugar to (typeof user.address == object user.address != null)? ? Yeah, it's also just an example, any (but the most efficient) desugared variant can be used. Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Existential operator
Hi, (I separate it from recent thread on shared handlers for proxies). The existential operator is a syntactic sugar to avoid long testing whether a property exists and only after that to apply it. This already is again used in CoffeeScript, so I'll show the examples: let street = user.address?.street which desugars e.g. into: street = (typeof user.address != undefined user.address != null) ? user.address.street : undefined; The same with functions (which is even more convenient that just with properties): let value = entity.getBounds?().direction?.x which desugars into: let x = (typeof entity.getBounds == function) ? (typeof entity.getBounds().direction != undefined entity.getBounds().direction != null) ? entity.getBounds().direction.x : undefined undefined; (I specially avoid optimization with saving intermediate results -- just to keep clarity) I think it's useful thing and I already used in several times. Do we need it in ES6? It's convenient. Another examples (which already as I know were planed for ES6, such as ||= or ?=, etc): score ?= 0 desugars into (notice, there's no unnecessary assignment as in score = score || 0; also, this sugar assumes that `score` may not even exists): (typeof score != undefined score != null) : score ? (score = 0); Normally, it can be done (assuming that `score` exists): score || (score = 0); so score ?= 0 is really just a sugar, no more, no less. Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Existential operator
On 13.04.2011 16:57, Brendan Eich wrote: See http://wiki.ecmascript.org/doku.php?id=strawman:default_operator -- the proposal there is ?? and ??= since single ? is ambiguous after an expression due to conditional expressions (?:). On Apr 13, 2011, at 11:37 AM, Dmitry A. Soshnikov wrote: let street = user.address?.street which desugars e.g. into: street = (typeof user.address != undefined user.address != null) ? user.address.street : undefined; (Just user.address != null would be enough, although perhaps there's a reason to typeof-test for undefined first that I am missing.) Yes, != would be enough for property accessor. But the proposal assumes to test for existence of the global vars as well (where normally we would got ReferenceError): let foo = bar?.baz (regardless that ES6 will have compile-time bindings, it still possible to create global var at runtime via `this.bar`, though, if there will be no global object, I'm not sure how this applies to the ES6) The same with functions (which is even more convenient that just with properties): let value = entity.getBounds?().direction?.x which desugars into: let x = (typeof entity.getBounds == function) ? (typeof entity.getBounds().direction != undefined entity.getBounds().direction != null) ? entity.getBounds().direction.x : undefined undefined; (I specially avoid optimization with saving intermediate results -- just to keep clarity) (Let's hope getBounds has no side effects :-P) Yeah, right ;) The ?. form from CoffeeScript is attractive at first glance. For notifying an ad-hoc observer where the reference to the observer may be null or undefined, it saves an 'if'. But for deeper optional control flow you need an 'if' anyway, in my experience. Yes, of course for some complex `if`s it's better to use `if`s. However, this: if (foo.bar) { if (foo.bar.baz) { if (typeof foo.bar.baz.quax == function) { foo.bar.baz.quax(value) } } } is too noisy in contrast with: foo.bar?.baz?quax(value); and first of all, this syntactic sugar is proposed exactly this such cases. How much is this used in CoffeeScript compared to regular .? Some crude measurement would be helpful. Can't say precisely (and even roughly). But personally I used it pair of times, it was convenient. Notice also, this form can be used even in this view: let foo = bar? baz? : true : false; which tests for exactly existence of bar and baz. And default values are also the case sure: foo ?= default // or foo ?? default (no matter much) Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Existential operator
On 13.04.2011 17:38, Kyle Simpson wrote: See http://wiki.ecmascript.org/doku.php?id=strawman:default_operator -- the proposal there is ?? and ??= since single ? is ambiguous after an expression due to conditional expressions (?:). The default operator doesn't address a significant part of what Dmitry is asking for -- the . in the ?. usage -- which allows the property access to be expressed only once and used for both the test and assignment. let street = user.address?.street which desugars e.g. into: street = (typeof user.address != undefined user.address != null) ? user.address.street : undefined; Part of what Dmitry asked for, I'd like to see in the plain ?: operator, and it seems like it would be possible to disambiguate from a top-down parser perspective. I would like to see the `:` (else condition) portion of a ?: expression be optional. For instance: var a = b ? c; // aka, `var a = b ? c : undefined` Hm, intuitively the form `a = b ? c` sounds for me as: a = b ? b : c Dmitry. The other (more awkward/obscure looking) way to do this is: var a; b a = c; The difference between the sytnax sugar I'm asking for and the default operator in the strawman is that ?: (or ) allows for separate expressions for the test (`b`) and the success_value (`c`), whereas ?? requires that the test expression and success_value be the same expression. For instance: var a = (b 5) ? b : undefined; In this case, the ?? default operator is of no use. But being able to drop the `: undefined` part, and also avoid using the more awkward looking syntax, would certainly be a useful sugar. --Kyle ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Existential operator
On 13.04.2011 21:57, Brendan Eich wrote: On Apr 13, 2011, at 3:38 PM, Kyle Simpson wrote: See http://wiki.ecmascript.org/doku.php?id=strawman:default_operator -- the proposal there is ?? and ??= since single ? is ambiguous after an expression due to conditional expressions (?:). The default operator doesn't address a significant part of what Dmitry is asking for -- the . in the ?. usage -- which allows the property access to be expressed only once and used for both the test and assignment. This was a one-line FYI, and on-topic in reply to Dmitry's post since he brought up ?= (spelled ??= in the strawman). Why are you objecting to it? Moving right along... let street = user.address?.street which desugars e.g. into: street = (typeof user.address != undefined user.address != null) ? user.address.street : undefined; Part of what Dmitry asked for, I'd like to see in the plain ?: operator, and it seems like it would be possible to disambiguate from a top-down parser perspective. I would like to see the `:` (else condition) portion of a ?: expression be optional. For instance: var a = b ? c; // aka, `var a = b ? c : undefined` The other (more awkward/obscure looking) way to do this is: var a; b a = c; First, making : optional introduces a dangling-else ambiguity: x = a ? b ? c : d; This could be (x = a ? (b ? c : d)) or (x = a ? (b ? c) : d). True, if-else already has this (traditional in C-based languages) ambiguity, resolved by associating : with the inner ? and so requiring the programmer to use braces if the other association is wanted, or in general just to avoid trouble. But why should we add more of the same kind of ambiguity, given the benefit of hindsight? Yeah, right, no new ambiguities are needed. Second, as I see Garrett asked in followup, why not simply write: var a = b c; If b is falsy but not undefined, and you don't want its falsy value propagating to a, then of course you'll have to write out: var a = b ? c : undefined; or: var a; if (b) { a = c; } or equivalent. Yes, or (which today is used as a better alternative of the default value): b (a = c); (though, this doesn't assign `undefined` to `c` in case of failur) This approach is used to avoid unnecessary assignment to itself. Instead of: foo = foo || default; better replacement is: foo || (foo = default); Another example: Array.prototype.map || Array.prototype.map = function () { /* map implementation */ }; And of course from this viewpoint special default operator (again, no matter much in which exactly syntactic form -- ??, ?=, ??=, ||=, etc) is good. Dmitry. but this seems like a hard case, and as they teach first year law students, those make bad law. The difference between the sytnax sugar I'm asking for and the default operator in the strawman is that ?: (or) allows for separate expressions for the test (`b`) and the success_value (`c`), whereas ?? requires that the test expression and success_value be the same expression. For instance: var a = (b 5) ? b : undefined; In this case, the ?? default operator is of no use. But being able to drop the `: undefined` part, and also avoid using the more awkward looking syntax, would certainly be a useful sugar. I think the dangling else problem is enough to nix this, but I welcome other comments. I'm also not sure b is falsy but not undefined in practice. It seems contrived to want a numeric value sometimes, and undefined others. IOW, var a = (b 5) ? b : undefined; looks like a bug that will result in undefined or NaN values propagating via a, some of the time, into other numeric or number to string expressions. It looks like a mis-coded min against 5. I don't see any ?. use case here, so I'm still not sure what this has to do with Dmitry's post or my reply. The topic in the Subject: line is CoffeeScript's existential operator, not anything that might be spelled with a ? -- but it's ok, we can discuss. Just please don't take me to task for citing a relevant strawman in reply to someone else's post that brought up (among several things) exactly what the strawman proposes, namely ??=. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Existential operator
On 13.04.2011 22:25, Brendan Eich wrote: On Apr 13, 2011, at 8:01 PM, Dmitry A. Soshnikov wrote: (regardless that ES6 will have compile-time bindings, it still possible to create global var at runtime via `this.bar`, though, if there will be no global object, I'm not sure how this applies to the ES6) No, Harmony won't alias this to the global scope (which is lexical, not an object). Yeah, quite a normal implementation. But I'm curious how will it be possible to address a dynamically formed property name -- the name of the global var? this[foo + bar] It'll be the WindowProxy as usual, in top level code. Dave has addressed what it will be in a module recently. I have to look on Dave's explanation, seems I missed it. But this WindowProxy won't be assessable then, right? Will it be possible to define a new global property/variable at all at runtime depending on condition? is too noisy in contrast with: foo.bar?.baz?quax(value); and first of all, this syntactic sugar is proposed exactly this such cases. Did you leave out a . after the second . in that example? Oh, yes of course, sorry. I had dinner with Jeremy Ashkenas last month, and he testified that CoffeeScript's disamgibuator pass (between lexing and parsing) is a work in progress and a work of (literately programmed) random logic, which he has tweaked based on user bug reports, even recently. You mean it was hard for Coffee to implement this foo?.bar? etc? This is not something to put into ECMA-262. So a postfix ? operator seems right out as a general operator, given ?: and ??/??=. Sorry, I didn't get from these two sentences -- whether postfix ? is good or not? :D (really sorry, just a translation hardness). How much is this used in CoffeeScript compared to regular .? Some crude measurement would be helpful. Can't say precisely (and even roughly). But personally I used it pair of times, it was convenient. Notice also, this form can be used even in this view: let foo = bar? baz? : true : false; which tests for exactly existence of bar and baz. OTOH, if ? as an identifier suffix, no space allowed, were added to Harmony, then we would have a migration tax in the form of an early error, which *might* be ok: // old code, note lack of space between a and ? x = a? b : c; Hm, not good. The whole ambiguity of this construct with casual a ? : c already makes it not good for me. And by the way, Coffee didn't have ? : it uses inline if - then instead. (well, actually it's possible to write in Coffee a = b ? b : c, but it compiles into completely different semantics). Harmony treating ? as an identifier suffix as an existential test would then find the run-on fragment b : c; a syntax error. Yes, I got it. This still seems a bit shaky. Is it important compared to ?. and part of the same package deal? Don't know, not so seems. And by the way, in my view, the operator is not ?. (i.e. a question followed by a dot), but still just ?. The following dot is already about property accessor: foo.bar?.baz again, bar? is separated, and only after that it's accessed to `baz` via casual dot notation. Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: When is a JavaScript program correct? (was: Setting a property in the prototype chain?)
On 11.04.2011 18:07, Mark S. Miller wrote: On Sun, Apr 10, 2011 at 11:21 PM, David Herman dher...@mozilla.com mailto:dher...@mozilla.com wrote: I wondered if someone was going to make this point. That should be while (!{}.hasOwnProperty.call(obj, key)) which works even if obj has an own property named 'hasOwnProperty'. Not if someone mutates Object.prototype.hasOwnProperty or Function.prototype.call. I don't think we need to polish a proof of concept. First, I agree that for the original purpose of this thread, this polishing is irrelevant, so I have changed the subject. But your counter-examples do help to highlight something I've been thinking about. Because of such pervasive mutability, we really haven't had a clear notion of correctness for JavaScript. For normal JavaScript programs, if run after some other code has already mutated that environment's primordials arbitrarily, there's so little they can count on that very few programs could be written correctly under these onerous assumptions[1]. For the notion of correctness in JavaScript to be useful, I think we must allow JavaScript programs to rely on the primordial at least continuing to obey their original contract. However, the use of objects as maps from strings to values is pervasive, e.g., in JSON unserialization, so we should not allow general purpose JavaScript programs to rely on, for example, 'hasOwnProperty' not being overridden. Retrofitting a reasonable theory of correctness after the fact is a tricky exercise. The above theory represents a practical compromise between the assumption that common programs make (primordials obey their original contracts) vs. the assumptions that common programs break (hasOwnProperty is not overridden). Thus, I claim that the original program should not be considered correct, while the modified program should, despite the problematic cases raised by your counter-example. As I see it, you address the issue of unstratified meta-programming (note, I take the issue in quotes, since there's no a single meaning whether the unstratified meta-level is so bad). It depends on how to look on the issue. On one hand, why if a user changes the behavior of the `hasOwnProperty` of _his_ object in _his_ program, then the program should be considered as incorrect? The user knows how to handle `hasOwnProperty` for the particular object and the ability to override it is the ability to control unstratified meta-level via simple reassigning to meta-hooks. On the other hand, yes, since we have the ability to modify any JS code via console or even via browser address bar (using pseudo-protocol javascript:), then it can be viewed as the issue and as a security program. But the salvation by the big deal should not be found in making a dynamic language as a completely frozen and static, but in the disallowing of code modification (code injection, code poisoning if you will) via such a simple tools as the console or address bar. Having the ability to inject the needed code via console just makes e.g. browser scripting as just an _addition_ for the server code. This is in case if we have combined client-server application. It's obvious, that if we have some validation tool, then the validation on the client side should be done only as the _convenient addition_. But the same validation will be done on the server, since we understand that the client code can be easily injected (the simplest example e.g. utils.validate = function () { return true; } which always will return positive result). If we have only client-side application, then the user, if breaks some code via injection just breaks his own page and therefore just refuses the convenience we wanted to give him. He doesn't break anything besides his own page. So that's the language is dynamic and allow to change objects in runtime is not in my view about correctness of a program. A programmer, having control of his code, knows how and why he wants to augment and modify his current runtime objects and code. From this viewpoint I don't think we need to disallow modifying of `hasOwnProperty` and similar. Better then to reuse ES5 approach and separate this meta-operation to Object.hasOwnProperty(foo). The fact that a language is static perhaps doesn't cancel the fact that the code still can be injected, etc. So again, IMO a correct program is not about let's freeze everything here. And predefined and predicted contract also relates to statics mostly. In duck typing exactly this contract can be achieved during the runtime -- one line before an object cannot pass the duck-test, on the other line (after some mutations) it already can do this, it satisfies the contract -- and it's achieved not via statics in the language. Dmitry. [1] SES initialization freezes the primordials, so SES programs can safely assume they are frozen. But the point I'm
Re: Setting a property in the prototype chain?
On 10.04.2011 21:24, Axel Rauschmayer wrote: As far as I am aware, there is no way to change a property that isn’t at the beginning of the property chain, because the change will create a new property there. Are there plans to change this? It would be nice to have something akin to class methods (without accessing the prototype via some other, e.g. global, reference). Inherited accessor property can be change normally via assignment. Also `Object.defineProperty` is a way. Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Questions about Harmony Modules
On 04.04.2011 18:40, David Herman wrote: Though the other question is: why do we need `require` at all? Purely for syntactic/practical reasons. Let's not bikeshed. Why I was asking -- because I saw it in your talk on ES.next, where you used exactly this approach, i.e. module Foo = http://modules.com/foo.js; -- without any `require`. That's it. (should I fix my following presentation also? I used the same as in yours) Agreed on rest points. Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Questions about Harmony Modules
On 03.04.2011 3:33, David Herman wrote: Hi James, 1) Files as modules do not need module wrapper Just to confirm, if a JS file contains only a module definition, the module X{} wrapper is not needed? That's correct. 2) Set module export value Is it possible to support setting the value of the module to be a function or some other value? Currently, there's nothing like this in the proposal, but I remember you blogged about this before. Harmony modules are static entities, and setting their value dynamically would clash with the design goals of static importing and exporting. That said, we could consider adding functionality to make a module callable, to address the use case you describe. Thanks for bringing this up. 3) Are module and import needed inside a module? There are two questions here: 3a) Is module needed inside a module? Yes. A module declaration declares a binding to a static module. A let/var declaration declares a binding to a dynamic value. You only get compile-time linking and scoping with static modules. 3b) Is import needed inside a module? I think the answer here is technically no. You're right that you could generally use let/var and destructuring, except for the import M.* case. If we allowed you to destructure a runtime expression and dynamically bind all its variables, we would be re-introducing `with' into Harmony, which we will never, ever, ever do. :) Yes, since technically it's possible to get a value of an exported binding directly via: let foo = Mod.foo; then it should be possible to use destructuring to get references for several bindings. However, as noticed, such imported via assignment bindings aren't static. I.e. it's possible e.g to assign to them in contrast if the binding is imported. Here I showed this difference: https://gist.github.com/885534 While this example is shown on prototyped modules in Narcissus, actually technically for real modules implementation there can be overloaded operator of assignment which calls `defineProperty` instead to make the binding the same as it was imported. Regarding, import M.* via destructuring, it's also arguable whether we don't need it since it looks like a with. Besides, if we can import all via partial destructuring, i.e.: module Mod { export foo var = 10; export bar var = 20; } let {foo, bar} = Mod; then (theoretically!) why not to have `let {} = Mod` (or any other syntax, e.g. let * = Mod). But, IMO it just looks more complicated than import Mod.*. So I would disallow `let {} = Mod` not because of `with`, but because of the oddness of the construction which sounds as destruct the module Mod into the empty object. The other difference -- at least in the current state of the proposal -- is that you can't use a `require' form in an ordinary expression, only in the RHS of an import/module declaration. This doesn't show up in the Geometry example you cited, but if you wanted to import from an external module using `let', you would have to use the callback API: ModuleLoader.load(geometry.js, function(Geometry) { let { draw } = Geometry; ... }); (We've talked a little bit about generalizing the `require' form to be an expression operator that does a static module load, but I'm not sure whether it hangs together.) This is the question of allowing expression which we talked in the Narcissus list (https://mail.mozilla.org/pipermail/narcissus/2011-March/43.html ; btw, is it worth to put the discussing on duplications on this list?). Though the other question is: why do we need `require` at all? Why not just: // loading from the local file system module $ = ./selector.js; // loading from Net module Widgets = http://mysite.com/widgets.cs;; Though, I see the only case with destructuring (assuming that the module isn't on local system): let {foo, bar} = require http://mysite.com/widgets.cs; But since you notice that `require` won't be allowed in such expression, I don't see why it's needed at all. Besides, I can imagine something like this: import widgets/panel which loads file panel.js from the widgets directory and either creates the module binding name as `Panel` (i.e corresponding to the file name), or imports all bindings from the module. Another variant: import widgets/panel {foo, myBar: bar} or import {foo, myBar: bar} from widgets/panel Dmitry. The end goal is trying limit the number of new special things in the language the developer needs to learn for modules. Ideally it would be: use 'module' to declare an inline module, then use require('') inside it to get handles on other modules, and use var/let and destructuring as you normally would. For many cases, I think that's fine. But .* is an important convenience for scripting. Also, FWIW, import is already reserved and has symmetry with export, so it seems like a wasted opportunity to
Re: extends keyword instead of superclass ...
On 30.03.2011 1:24, Allen Wirfs-Brock wrote: On Mar 29, 2011, at 12:14 AM, Dmitry A. Soshnikov wrote: On 29.03.2011 2:51, Allen Wirfs-Brock wrote: ... Regarding classes in general I have the following table of classes kinds: |first-class | second-class (or first-order) |--- |--- dynamic |Ruby, Python, JS, Coffee| ? static |freeze(class) | C++, Java Thus, combination of statics + second-class can give us an immutable type with strong predefined behavior and set of properties. FWIW, according to this model, Smalltalk has a static, first-class classes and I believe most of your points below also apply to such languages Yes, I believe it's so. First-class property doesn't cancel the fact that a class is equals to type. First-class / Second-class are just about the ability to use the class as a value (to pass as arguments, return, etc), no more, no less. Actually, the borders of all these definition are smoothed. E.g. Python's classes (and it has first-class dynamic/static classes) are also just a syntactic sugar over the delegation-based inheritance (nearly the same of what is planned in this strawman). But Python names its classes as types (according to `type` operator). class A(object): pass a = A() print(type(a) == A) # True # the class is a first-class value def foo(Class): print(Class) # i.e. we may e.g. pass it as argument foo(A) # class '__main__.A' # the (user) class is dynamic # we may extend it with a new prototype property A.x = 10; # and already existing instance # has the access to this new property print(a.x) # 10, via delegation # and we may shadow it with own property a.x = 20 # own property print(a.x) # 20, own del a.x # remove own print(a.x) # again 10, via delegation from prototype - class So I think we should mostly concentrate on real practical application of what we want to set/get from classes as sugar and less on some theoretical things (which though also important in the design of a language). This is how I see it of what we need: We need the sugar for better classified programming. I.e. we need an ability to conveniently describe a _shape_ (a pattern) of objects which will have this shape, which will be generate by this pattern (by this classification). Thus, assuming dynamics, we may want not to define this shape as static. If a user wants to, he/she can mutate classes/objects at runtime with monkey-patching. We may provide some derived functionality for membership and feature testing such as property class -- for getting the class from the instance, class.super -- for getting the superclass, etc (involving already existing `instanceof`, etc). To stratify meta-level, we may want to use Class.getClass(object) instead of object.class (or even better, Object.getClass(object) which nearly equal to object.constructor) and Class.getSuperclass(aClass) instead ob aClass.super. The user at the same time is free not to use all these `instanceof`, etc checking the hierarchy membership, but instead to use Duck-testing, i.e. a direct feature testing -- if (isFunction(object.read)) { ... OK and no matter what's the class of the object ... }. Though, not in all cases such tests are acceptable. In dynamic classes first-class classes, a type as a set of predefined and immutable things is not so important. Moreover, for feature-testing, as a type-tag or better to say as a classification-tag can be used just a simple property of an object which helps to distinguish an object of yours classification from the object with the same state. foo.class == Foo; // true -- testing with a class-tag foo instanceof Foo; // true It's enough for dynamic first-class classes, and substitution principle may not be so important. Moreover, even here, e.g. the following substitution works fine: bar instanceof Bar; // true bar instanceof Foo; // true, assuming that Bar is a subclass of Foo And the set of methods and properties in the dynamic classes of course can vary over the time. And of course in such a system we cannot predict whether will be able to substitute an instance after some mutations (removing/addition methods, etc). But repeat, it's not so required hard in the dynamic system. But if you still want be sure, the just make them completely frozen (i.e. static classes) and then you can be sure. There is much Smalltalk experience that shows that class testing leads to code that is less maintainable or less reusable. Smalltalk style guides (for example see http://stephane.ducasse.free.fr/FreeBooks/WithStyle/SmalltalkWithStyle.pdf ) invariably contained items like don't test for a specific class and don't use isKindOf: or isMemberOf: (tests for inherited/direct class membership). The reason is that you should care more about the behavioral contract of an object
Re: extends keyword instead of superclass ...
On 29.03.2011 2:51, Allen Wirfs-Brock wrote: On Mar 28, 2011, at 1:53 PM, Dmitry A. Soshnikov wrote: Exactly. Classes are not about just the class keyword, but about the _ability to classify_, i.e. to program in classified (i.e. with object-patterned programming). JS supports (and supported all these years both approaches: delegation-based prototypal (i.e. unclassified or chaotic code reuse) and classical (classified or systematized code reuse). To quote the title of a famous paper by William Cook: Inheritance Is Not Subtyping. This is commonly misquoted as Subclassing is not Subtyping. Thus, a class in JS is a pair of constructor function + prototype. From this viewpoint, e.g. classes in Python (or CoffeeScript) are just syntactic sugar of the same delegation-based inheritance used in JS. And this means that JS also may have this sugar -- to allow users to program in classified manner (if they need to). So there's no a big difference between these languages and therefore keyword `extends` may fit absolutely normally. And quoting the definition of class in /Smalltalk-80: The Langauge and Its Implementation/: class: A description of a group of similar objects. I would emphasize the word description in the Smalltalk-80 definition. In dynamic object oriented languages, a class consists of the description of the common implementation of a set of identically implemented objects. Part of that common implementation may be obtained via inheritance. But obtaining parts of an object's implementation via inheritance (subclassing) is not the same as subtyping. Subtyping implies a substitutive relationship. If B is a subtype of A, then in general you can expect to be able to substitute B in any situation where A is expected. Static object oriented languages in the style of C++, Java, and C# fairly strongly equate subclassing with subtyping. What you can say in a class definition is constrained by the rules of subtyping. Dynamic object-oriented languages such as Smalltalk, Ruby, and Python do not equate subclassing and subtyping. In such languages, B being a subclass of A means that B shares some of it implementation with A but it does not mean that B can always be substituted for A Allen, all this is correct, though I guess we understand that we talk about not subtyping as substitution principle (by Liskov), but about the _sugar for generation of objects with the same structure_ -- to improve code reuse. Regarding classes in general I have the following table of classes kinds: |first-class | second-class (or first-order) |--- |--- dynamic |Ruby, Python, JS, Coffee| ? static |freeze(class) | C++, Java Thus, combination of statics + second-class can give us an immutable type with strong predefined behavior and set of properties. In dynamic classes first-class classes, a type as a set of predefined and immutable things is not so important. Moreover, for feature-testing, as a type-tag or better to say as a classification-tag can be used just a simple property of an object which helps to distinguish an object of yours classification from the object with the same state. foo.class == Foo; // true -- testing with a class-tag foo instanceof Foo; // true It's enough for dynamic first-class classes, and substitution principle may not be so important. Moreover, even here, e.g. the following substitution works fine: bar instanceof Bar; // true bar instanceof Foo; // true, assuming that Bar is a subclass of Foo And the set of methods and properties in the dynamic classes of course can vary over the time. And of course in such a system we cannot predict whether will be able to substitute an instance after some mutations (removing/addition methods, etc). But repeat, it's not so required hard in the dynamic system. But if you still want be sure, the just make them completely frozen (i.e. static classes) and then you can be sure. So what is more important here (and exactly about it is your strawman as I understand, right?) is the syntactic sugar for exactly _convenient classified programming_. For the convinient classified generation of objects created by the specified (classified) _patterns_. And exactly from the _convenience of the usage_ of such a sugar I think we should start. One of the rules of object subtyping is that additional methods may be added by a subtype but methods may not be deleted. Thus in a subclassing==subtyping language it is easy to think about subclasses as generally extending superclasses with additional members. The use of extends in Java is no doubt a reflection of that perspective. Yes, that's true, but it seems a little bit as a nit-picking to exact syntax/terminology. Instead, we should concentrate on exactly the _convenient code reuse_ and _convenient classified
Re: extends keyword instead of superclass ...
On 28.03.2011 0:05, Brendan Eich wrote: On Mar 27, 2011, at 11:33 AM, Juan Ignacio Dopazo wrote: On Sat, Mar 26, 2011 at 6:31 PM, Dmitry A. Soshnikov dmitry.soshni...@gmail.com mailto:dmitry.soshni...@gmail.com wrote: Why not just to use already reserved `extends` keyword for specifying a superclass? These XML-like braces looks not so elegant. I asked this question a couple of days ago. The answer is quite simple. Object initializer extensions are more than just constructor syntax. They allow you to create complex objects without all the hassle in (function(){}()). So the constructor syntax was made this way to be consistent with object initializer syntax. The meta syntax (e.g., var obj = {proto: p, key: val}) is not inconsistent with initialisers, it's an extension to them. But it's not the only self-consistent extension. Dmitry mentioned letting the meta properties appear to be regular key: value pairs but distinguishing the keys with @ or #. Allen makes the point that class D extends B {...} may look too much like languages where it means something quite different. That's true, but I am not sure JS should be so special that it seems to mix bits of those languages into one (of several conceivable) extensions to initialiser syntax: class D {superclass B}; Whatever you think of the meta section, the leading 'class D {' telegraphs influence from, and just familiarity with, those other languages. And I don't think that is a bad thing even if semantics differ. Just changing 'class' to 'constructor' (adding a new perhaps-only-contextually reserved word, and a long one at that) is not the issue. Sure, doing that would in a text-only way make the syntax not look like any other language, exactly. But ignore the skin: the bones look familiar, going back to C structs. Now add some notion of inheritance and you're following the C++ body plan. Exactly. Classes are not about just the class keyword, but about the _ability to classify_, i.e. to program in classified (i.e. with object-patterned programming). JS supports (and supported all these years both approaches: delegation-based prototypal (i.e. unclassified or chaotic code reuse) and classical (classified or systematized code reuse). Thus, a class in JS is a pair of constructor function + prototype. From this viewpoint, e.g. classes in Python (or CoffeeScript) are just syntactic sugar of the same delegation-based inheritance used in JS. And this means that JS also may have this sugar -- to allow users to program in classified manner (if they need to). So there's no a big difference between these languages and therefore keyword `extends` may fit absolutely normally. Here how I see classes syntactic in JS (a combination of Coffee's sugar + Java's syntax, since we can't eliminate it). Notes: I think that usage of thing like: class method fromString() { .. } are to verbose. Don't think we need another keyword `method` at all. Also I used a syntactic sugar for `this` keyword as `@`. This `at` allows easily to define and distinguish class- and instance- methods. The rule is simple: if a property/method inside the class body starts with @ -- it's the class's property/method (i.e. `this` refers to class). In other case -- it's an instance method. @ evaluated inside the instance method refers of course to the instance. Here's a small example with sugared (on the left hand) and desugared (on the right hand side) views: http://bit.ly/hvS7hl Take a look please. And below is just an example without the desugaring. Thus, the definiton itself is in declarative form. Also I think it's good to provide both dynamic and static classes. By default I used dynamic classes, so `static` keyword is explicit. In the example I also used `include` keyword as an ability to mixin some module as a direct ancestor of an instance, i.e. before the class in the hierarchy. Mixins/traits will allow to reuse the code horizontally (not only with a single vertical inheritance tower). /* -- * Class Point definition * -- */ class Point { /** * Class method (placed on constructor function) */ @fromString: function (s) { return new Point(parse(s)); } /** * Instance intializer (aka constructor) */ initialize: function (x, y) { @move(x, y); } /** * Simple instance method (placed on prototype) */ move: function (x, y) { @x = x; @y = y; @repaint(); } /** * Class property (placed on constructor function) */ @x: 10 } /* -- * Class Point3D definition * -- */ static class Point3D extends Point { include Comparable; /** * Class static property */ @instances
Re: extends keyword instead of superclass ...
On 27.03.2011 22:33, Juan Ignacio Dopazo wrote: On Sat, Mar 26, 2011 at 6:31 PM, Dmitry A. Soshnikov dmitry.soshni...@gmail.com mailto:dmitry.soshni...@gmail.com wrote: Why not just to use already reserved `extends` keyword for specifying a superclass? These XML-like braces looks not so elegant. I asked this question a couple of days ago. Really? Sorry, seems I missed, I'll take a look (a direct link will be appreciated). The answer is quite simple. Object initializer extensions are more than just constructor syntax. They allow you to create complex objects without all the hassle in (function(){}()). So the constructor syntax was made this way to be consistent with object initializer syntax. There can be exception for at least class definition since `extends`, repeat, is/was already reserved and familiar to many programmers. Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
extends keyword instead of superclass ...
Hi, Just a small note on http://wiki.ecmascript.org/doku.php?id=strawman:super_in_object_initialisers (reading currently) Why not just to use already reserved `extends` keyword for specifying a superclass? These XML-like braces looks not so elegant. Coffee users the same classes syntactic sugar as planned for ES6: http://jashkenas.github.com/coffee-script/#classes and also reuses familiar (for all?) `extends` keyword of ES3. P.S.: This (XML-like syntax) relates also to other meta-properties/attributes in object initialisers. I prefer to use @ instead: let foo = { @proto: bar, @sealed, move: # (x, y) { ... } }; Though, again, e.g. Coffee (on Ruby's style) users `@` for `this`. Does JS need this sugar for `this`? In this case (since # is planned to be used actively) meta-properties can be: let foo = { #proto: bar, #sealed, move: # (x, y) { ... } }; Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: String.prototype.repeat
On 24.03.2011 0:44, Brendan Eich wrote: On Mar 23, 2011, at 12:57 PM, Dmitry A. Soshnikov wrote: Yep, I see. Btw, JFTR: such a mistake currently is in this strawman http://wiki.ecmascript.org/doku.php?id=strawman:shorter_function_syntax: let randomArray = Array(10).map(#{Math.random()}); Fixed, in a cheezy but I hope clear fashion. Yep, it's OK now; and this `NonHoleyArray` abstraction is also interesting. Meanwhile it's an abstraction, such a thing can be needed. And from this viewpoint I can imagine the same `fill` or `init` method, but which can accept not only the number of elements and the direct value for each element, but also a fill-function (indirect value). Then the user can do it in one pass then. E.g.: Array.fill(5, 0); // [0, 0, 0, 0] Array.fill(5, #{Math.random()}); [0.1, 0.3, 0.5, 1, 0] Dmitry. /be it's better to fix the doc. Dmitry. the answer is known of course (there's no any property in the created array), but similary to your String(n, '*'), there can be also Array.fill(100, 0); or Array.init(100, 0); P.S.: though, of course all these can be done manually in ES itself. Of course and these cases do not happen once a day. However, when they happen, it's convenient if the language offers a native construct. David Dmitry. In ES5, the String constructors (String and new String) both are expected to be used with zero or one argument, so using a two argument constructor should not break the web or people's expectations. David ___ es-discuss mailing list es-discuss@mozilla.org mailto:es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: String.prototype.repeat
On 24.03.2011 0:44, Brendan Eich wrote: On Mar 23, 2011, at 12:57 PM, Dmitry A. Soshnikov wrote: Yep, I see. Btw, JFTR: such a mistake currently is in this strawman http://wiki.ecmascript.org/doku.php?id=strawman:shorter_function_syntax: let randomArray = Array(10).map(#{Math.random()}); Fixed, in a cheezy but I hope clear fashion. There are other the same examples (with alternative syntax) in the strawman. let randomArray = Array(10).map(fn{Math.random()}); etc. Since # syntax is already (almost completely?) accepted, probably there's no a big need in mentioning all alternative which anyway won't be accepted. Though, it's of course good for the history. Dmitry. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: String.prototype.repeat
On 23.03.2011 0:18, David Bruant wrote: Le 22/03/2011 02:39, Dmitry A. Soshnikov a écrit : On 22.03.2011 23:42, David Bruant wrote: Hi, About the string_repeat strawman (http://wiki.ecmascript.org/doku.php?id=strawman:string_repeat), one alternative solution could be a two argument constructor. Something like: String(n, pattern). So, for the example in the strawman, it would be String(3, '*'). A little bit off-topic, but not so big off-topic. Recently on Twitter there was a question why it's not an array of zeros: Array(100).map(function() { return 0; }); // not the array of zeros It's not that much off-topic. I have made the mistake myself facing this issue :-) (https://bugs.ecmascript.org/show_bug.cgi?id=33#c6) Yep, I see. Btw, JFTR: such a mistake currently is in this strawman http://wiki.ecmascript.org/doku.php?id=strawman:shorter_function_syntax: let randomArray = Array(10).map(#{Math.random()}); it's better to fix the doc. Dmitry. the answer is known of course (there's no any property in the created array), but similary to your String(n, '*'), there can be also Array.fill(100, 0); or Array.init(100, 0); P.S.: though, of course all these can be done manually in ES itself. Of course and these cases do not happen once a day. However, when they happen, it's convenient if the language offers a native construct. David Dmitry. In ES5, the String constructors (String and new String) both are expected to be used with zero or one argument, so using a two argument constructor should not break the web or people's expectations. David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Standardizing __proto__
JFTR, I remember the previous the same discussion(s) and mentioned earlier the thing similar to this `Object.subclass`, though, just with providing an ability to specify the [[Class]] for `Object.create`. E.g. for a unclassified inheritance: let foo = Object.create(Array.prototype, Array, {...}); and for classified as well: // create new constructor, objects of which // inherit from Array.prototype and are real // arrays, additionally pass prototype properties var Foo = Constructor.create({ // objects kind class: Array, // an initializer constructor: function Foo(args) { this.push.apply(this, args); }, // prototype properties (also may // be added after Foo is created prototype: { size: { get: function getSize() { return this.length; } } } }); var foo = new Foo([1, 2, 3]); console.log(foo.length); // 3 foo.push(4, 5, 6); console.log(foo); // 1,2,3,4,5,6 console.log(foo.length); // 6 foo[7] = 8; console.log(foo); // 1,2,3,4,5,6,,8 foo.length = 3; console.log(foo); // 1,2,3 etc. Other examples: https://github.com/DmitrySoshnikov/es-laboratory/blob/master/examples/create.js P.S.: yeah, mutable __proto__ is (was?) and interesting feature, but we tried to find its _real_ practical wide-spread application and couldn't. The same as we couldn't find the big practical rationale of the Python's __class__ from which __proto__ is borrowed. Yes, repeat, it's interesting from the _completely dynamic languages ideology_ (I like to show examples of first-class dynamic classes as oppose to second-class static classes), but if to start just analyze and try get again -- _real_ practical application, -- well, it's not so easy. Some internal lib hacks as mentioned by John cannot be considered as practically widely spread. So the mutable __proto__ (no matter in which name and view) can be standardized only if (1) no security issues, (2.1) practically needed or (2.2) just a cool stuff of dynamic languages with unfortunately small practical application. To avoid i-looping, Object.setPrototype(object, parent); is better than __proto__ of course. Dmitry. On 18.03.2011 22:36, David Bruant wrote: Le 18/03/2011 18:00, Oliver Hunt a écrit : I kind of dislike the proliferation of .create methods. It's seems inelegant. What if we had (use __proto__ for semantic description) Object.subclass = function(constructor) { use strict; function cons() { var result = constructor.apply(this, arguments); result.__proto__ = cons.prototype; return result; } cons.prototype = Object.create(constructor.prototype); return cons; } Mike Shaver: Andreas in IM that we hang it on the prototype chain, so that we get it everywhere without repetitive specification. How about: Function.prototype.createDelegatingTo = function (obj) { var o = new this; // really new-with-apply(arguments) here o.__proto__ = obj; return o; } One difference I see between Object.subclass and Function.prototype.createDelegatingTo is that the latter does not enforce anything on the prototype. -- ( Array.createDelegatingTo({}) ) instanceof Array === false // while ( new Object.subclass(Array) ) instanceof Array === true -- On the other hand, Function.prototype.createDelegatingTo is more expressive and Object.subclass can be implemented from it. If methods such as Array.create are to be considered, this issue of enforcing Array.prototype will have to be addressed. I have personnally no strong conviction on one side or the other. David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss