Re: Promise.cast and Promise.resolve
On 8 February 2014 07:37, Benjamin (Inglor) Gruenbaum ing...@gmail.comwrote: -- Forwarded message -- From: Brendan Eich bren...@mozilla.com To: Kevin Smith zenpars...@gmail.com Cc: Mark S. Miller erig...@google.com, EcmaScript es-discuss@mozilla.org Date: Fri, 07 Feb 2014 16:05:20 -0500 Subject: Re: Promise.cast and Promise.resolve A *working* implementation should be created and solutions to real-world use cases should be programmed using the design before any spec language is authored. Spec-language is apoor medium for communicating both design intent and programming intent. Yes, this. I just want to add my two cents on this part here. A lot of us are following this thread from the outside, being unable to keep track of all the meetings ambiguities and agreements and the such. Tracking it is hard with all the ambiguities and 'big words' people sometimes throw and unclear use cases. The way 'we' see it is: - Promises solve an interesting problem They do. And that problem is representing the eventual value of asynchronous computations, allowing you to compose them as usual. (there are different approaches to this too) - There are a number of promise libraries that are *working* implementations that solve real world use cases. They have evolved for several years _for_ those use cases. - I believe that was a big consideration for adding them to the specification to begin with. - Promise libraries _could_ have added some of the methods and alternatives discussed here but didn't. - Q is not the only library nor it is the 'de facto standard'. Kris is very knowledgeable but was not the only one building APIs. There are at least 4 more libraries that do promises (RSVP, When, Bluebird, kew, vow...). .chain , while very interesting is not very common to say the least. - Tens of thousands (probably more) of people have been using these libraries for years now. Well, promises are a fairly old concept, with several different implementations throughout the history of CompSci, and even in JavaScript land itself. `.chain` itself is not common because it doesn't need to have that name, but it is a common operation (`.then` encodes that operation, for example, but you can't control when it gets applied). As for working implementations of `.chain-able` promises, you can see: https://github.com/folktale/data.future#example, and https://github.com/fantasyland/fantasy-promises, although they are not Promises/A+, it should be easy enough to implement `.cast` and `.then` on top of those primitives. There are three things you want to do with a promise: - You want to sequence asynchronous computations, such that you can specify computations that depend on a particular value. This is what `.chain` does. - You want to transform the value of a computation, but the computation itself is synchronous. This is what `.map` does, and `.chain` can generalise `.map`. - You want to assimilate the result of a different promise. This is what `.cast` does. Unfortunately, Promises/A+ only provide you with a `.then` method, which does all of those things for you, but you can never control which of those gets applied. Thus, `.chain` is a more general approach, and `.then` can be easily derived from `.chain`. A specification should favour the general use cases to make it easy for people to write more specific computations in userland, instead of constraining the expressive power to particular higher-level use cases. This is what the discussion on Promises right now is about. I mean no disrespect to the hard work of the people here. I know everyone who is participating in the discussion here is putting a lot of time and effort to better the language and the community. However, from my complete outside it sounds like: - There is a working tested solution that evolved through usage and solving real problems over several years*. * - The committee is dictating a lot of changes for it. - Changes are based on new design goals and theoretical considerations like purity. I'm not saying there are no very good arguments for non-recursive assimilation and .chain (there are) , but they're still being dictated over existing library solutions. I was under the impression the goal is to adopt what works in practice as much as possible and not dictate solutions from the sky. If someone wants `a different API there is nothing preventing them from creating a library and doing that - then coming back with Hey, our solution works, we have 1000 dependencies on NPM or on second thought, that sounded very interesting but people are complaining about usage. One of the problems with just following existing solutions is that you'd also be copying the evolution mistakes and technical debts in those solutions. The committee **is** considering the existing solutions, and the use cases presented by people, which is a good thing. For example, for the asynchronous map use case,
Re: Promise.cast and Promise.resolve
On 8 February 2014 12:26, Benjamin (Inglor) Gruenbaum ing...@gmail.comwrote: On Sat, Feb 8, 2014 at 2:57 PM, Quildreen Motta quildr...@gmail.comwrote: One of the problems with just following existing solutions is that you'd also be copying the evolution mistakes and technical debts in those solutions. The committee **is** considering the existing solutions, and the use cases presented by people, which is a good thing. For example, for the asynchronous map use case, `.then()` is not usable short of adding plenty of special cases, and special cases don't compose cleanly. Standards are difficult because what you decide will shape the solutions that people write in the language for decades, standards evolve slowly, that's why you have less chances to make mistakes — in a library you can make a mistake and promptly fix it in the next version, this is not true of standards. My problem with that paragraph is that promise libraries _have_ evolved for years. There are several libraries - Bluebird, Q, when, RSVP or any other promise library with _a lot_ of dependent libraries on NPM and more than a thousand stars on GH. They're all open source and At any point anyone could have: - Add 'chain' with a PR, explain why it's better and convince _any one of those_ maintainers why it should be added. I've seen work in Promise libraries several times. - Open an issue with convincing real life use cases and explain them - advocate .chain and get people to use it. I've seen this work in promise libraries several times and have done so myself. - Fork any one of them (most, if not all have permissive MIT licenses) and replace .then with .chain (or add it). It's also no problem to interop with existing A* libraries. - Build a new library and get users - I personally recently converted over 100 KLOC to use a promise library that didn't exist a year ago. I'd just like to add I did not make (at least intentionally) a single technical argument here. It's merely the process I'm concerned about. Choosing APIs that have no extensive use in the ecosystem over ones who do without first battle testing them concerns me. It has been discussed at length before ( https://github.com/promises-aplus/promises-spec/issues/94), and continued in es-discuss. Specially because there are use cases for the standard library that are not covered by `.then` (Andreas has discussed them before). And again `.then` is just a special case of `.chain`, so the proposal that was being discussed was to give people `.chain` and `.then`, where `.then` would be written in terms of `.chain`. -- -- Quildreen (Soreλ\a) Motta (http://robotlolita.github.io/) *— JavaScript Alchemist / Minimalist Designer / PLT hobbyist —* ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Promise.cast and Promise.resolve
I can understand the you can't have your cake and eat it too sentiment. Indeed, I do think that having `.then()` and `.chain()` in the spec is a mistake. The only thing that saddens me (and this also with some other parts of the spec, such as Object.create) is that `.then()` is not an orthogonal and composable primitive, it's a multi-method on top of simpler primitives, but as with other parts of JavaScript, the simpler, orthogonal primitives are not available for users to derive more complex functionality from easily. That is, these higher-level primitives provide support to a class of higher-level use cases, but not the necessary basis to support these use cases in general, and this is a bummer for modularity and re-usability. More so, I do think that just following de-facto standards without acknowledging that there might be bugs on them you want to fix when they are cheap to do so (i.e.: now, rather than after it becomes standard) really bothers me. Fixing libraries today, specially with a relatively new thing such as Promises/A+ is relatively cheap. At any rate, I'm just venting now, and I agree that the spec should only support either one or the other (even if `.then()` is just a combinator, the addition of it on the specs would lead to unnecessary headache, since it doesn't compose cleanly with other constructs). I am just sad that the specs are once again favouring the higher-level, limited use cases. On 5 February 2014 12:39, Mark S. Miller erig...@google.com wrote: On Wed, Feb 5, 2014 at 6:37 AM, Mark S. Miller erig...@google.com wrote: On Wed, Feb 5, 2014 at 12:43 AM, Brendan Eich bren...@mozilla.comwrote: Kevin Smith wrote: - Promise.cast is renamed to Promise.resolve (remove old Promise.resolve) - Keep then, reject chain (NOT DEFER, reject!) - Renaming .cast thus removes over-wrapping (always-wrap) deoptimization in old Promise.resolve So basically, since September, we've seen: - A design proposal which achieved consensus - A spec implementation which completely ignored that consensus - And now a third design, which also throws out consensus and has been implemented by precisely no-one And all of this over 200 to 300 LOC. These shenanigans are deeply disturbing. I agree. I kept my nose out of it until it was front-and-center on the last day of the last TC39 meeting, and in context of threads here that were pushing (I was on side with you) to add .chain. The design proposal in September did not have consensus, for real. That proposal was changed after the September meeting (Mark has details). The implementation in V8 then added .chain based on an understanding from the May 2013 meeting (multiple, Rashomon views of consensus). There's still some concern about supporting Promise subclassing, too, but I think it can be handled without controversy (I could be wrong). It entails using the public-named methods (in case of overrides) consistently, and not using internal methods or other such shortcuts some of the time. Basically always use .then. Can we regain consensus on the September status quo ante, minus any do both half-hearted compromises that don't work? Mark, what do you think? I see no need to reopen this yet again. At this last meeting, we declared a new consensus, to keep the .cast and .then level, dispense with the .accept (previously renamed .resolve) and .chain level, and to rename .cast to .resolve. This kills the September AP2 consensus, in that we are no longer constraining the .then level's mechanics to be compatible with introducing (whether now or in the future) a .chain level. The September consensus was a compromise, in the do both mode that standards committees are tempted by. I have a deeper appreciation of those temptations now, having promoted it at the time. Given that we were trying to do both, Todd's AP2 was a wonderful way to minimize the pain. But I am now proud to see our committee once again rise above the do both failure mode. IMO, the most important argument against do both is that it would lead to perpetual confusion, as some libraries are written to the .then style and others are written to the .chain style. With AP2, these would live together as well as possible, but that's still not well. Regarding the comments in this thread, I haven't engaged since I have not seen any new points raised. All the old arguments are publicly archived. If you're about to repost a previously posted argument, please instead just go read the previously posted response. No one convinced anyone of very much that time, and repetition is unlikely to do better. The one remaining open issue for me is the means of flattening the output side of a .then operation. The end-of-september consensus flattened one level, but nominal typing and use of internal properties. Should be *by* nominal typing and use of internal properties. The current spec flattens using .then. The change was
Re: Promise.cast and Promise.resolve
On 29 January 2014 10:45, Paolo Amadini paolo.02@amadzone.org wrote: On 29/01/2014 5.12, Kris Kowal wrote: In this case, a half pursuit of type purity is a side quest at the expense of users. Having two ways to resolve and two ways to observe a promise is unnecessarily confusing. In my experience, one method like then, that unwraps recursively, and one function, like Promise.cast, that automatically lifts if necessary, and then handlers that return into the waiting hands of Promise.cast are coherent and ergonomic. Having a choice between cast and resolve and a choice between then and chain, will leave developers unnecessarily confused and worried all the while they use or abandon Promises as too subtle. As an imperative programmer, I confirm I'm left worried and confused ;-) But I understand that functional programming might need more complexity. It is, actually, more simplicity. The concept of `Promise.resolve` and `Promise.chain` is simpler than `Promise.cast` and `Promise.then` (i.e.: they represent orthogonal concepts, not complected). `Promise.cast` and `Promise.then` may be, arguably, *easier* to work with, from a user POV, since you don't need to make as many choices. I would argue that it would make more sense to write `cast` and `then` in terms of `resolve` and `chain`, however. But this seems to have already been decided. Answering your previous question: ```js var p1 = Promise.resolve(Promise.cast(1)); var p2 = Promise.cast(Promise.cast(1)); ``` `p1` will be a `Promise(Promise(1))`, whereas `p2` will be `Promise(1)` — IOW, `Promise.resolve` will just put anything inside of a `Promise`, regardless of that being a promise or a regular value, whereas `Promise.cast` will put the innermost value that is not a promise inside of a promise. ```js var p3 = new Promise(resolve = resolve(Promise.cast(1)); // is the same as: var p3 = Promise.resolve(Promise.cast(1)) ``` -- -- Quildreen (Soreλ\a) Motta (http://robotlolita.github.io/http://killdream.github.com/ ) *— JavaScript Alchemist / Minimalist Designer / PLT hobbyist —* ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Promise.cast and Promise.resolve
So, if I understand correctly, it basically boils down to: Promise.resolve :: a → Promise(a) Promise.cast :: a → Promise(a) Promise.cast :: Promise(a) → Promise(a) But right now we'll only get `.then`, so transformations with nested promises will flatMap automatically: Promise.then :: (Promise(a)) = ((a → MaybePromise(b), (a → MaybePromise(b)) Promise.then :: (Promise(Promise(a))) = ((a → MaybePromise(b), (a → MaybePromise(b)) But later, once `flatMap` is introduced, you'll be able to deal with nested promises without breaking parametricity: Promise.flatMap :: (Promise(a)) = (a → Promise(b)) If that's correct, I don't see any use cases for Promise.resolve right now, unless a library where to provide a corresponding unspecified `flatMap` implementation. On 28 January 2014 18:07, Paolo Amadini paolo.02@amadzone.org wrote: [Replying here since I'm not sure about how to move the discussion to the issue tracker without losing the context of Mark's observation.] On 28/01/2014 20.28, Mark S. Miller wrote: For people concerned only about the .then level of abstraction, I see little reason to ever use Promise.resolve rather than Promise.cast, and much reason to prefer Promise.cast. But fwiw we did agree to express the difference now, to be perceived by future and experimental uses of .flatMap in the future. I don't have a background on the .flatMap level of abstraction. In the following scenario, will users of getMyPromise() have a different behavior with .flatMap if the library code used cast rather than resolve? If so, this can definitely lead to confusion when .flatMap is introduced in the future since the callers cannot be sure about what the library did internally, assuming the library authors didn't intentionally choose one or the other. ```js // -- MyLibrary.js function getMyPromise() { var a = condition ? getMyOtherPromise() : value2; return Promise.resolve(a); } function getMyOtherPromise() { return Promise.resolve(value1); } ``` ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss -- -- Quildreen (Soreλ\a) Motta (http://robotlolita.github.io/http://killdream.github.com/ ) *— JavaScript Alchemist / Minimalist Designer / PLT hobbyist —* ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Promise.cast and Promise.resolve
On 28 January 2014 21:27, Andreas Rossberg rossb...@google.com wrote: On 28 January 2014 21:21, Quildreen Motta quildr...@gmail.com wrote: But later, once `flatMap` is introduced, you'll be able to deal with nested promises without breaking parametricity: Promise.flatMap :: (Promise(a)) = (a → Promise(b)) If that's correct, I don't see any use cases for Promise.resolve right now, unless a library where to provide a corresponding unspecified `flatMap` implementation. The V8 implementation provides it under the name `chain', with the obvious semantics. Considering that the fantasy-land specification uses the `chain` name as well, this is really neat. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Promise.cast and Promise.resolve
On 29 January 2014 01:27, Sam Tobin-Hochstadt sa...@cs.indiana.edu wrote: On Tue, Jan 28, 2014 at 7:47 PM, Brendan Eich bren...@mozilla.com wrote: Andreas Rossberg wrote: Seriously, Haskell calls it=. Right, that thing. Did it have the f-l-a-t-... name in Haskell, or is it pronounced b-i-n-d always, monads or not? No, it's always called bind in Haskell. The name flatMap was invented for Scala, to the best of my knowledge. I suppose using names that don't give you a hint of the meaning of the operation fits perfectly Haskell's (and Scalaz's) Avoid Success At All Costs tradition ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: JSCert: a JavaScript formalisation in the Coq theorem prover
Ah, this looks really neat! :D I wasn't familiar with any research on formalising JavaScript semantics besides λjs, so it's neat to see more research on this front :) On 25 January 2014 22:55, Gareth Smith g...@doc.ic.ac.uk wrote: Apologies if this is a duplicate - I tried sending this earlier, but it didn't seem to go through. Gareth Smith g...@doc.ic.ac.uk writes: We are pleased to announce JSCert, a formalisation of Chapters 8-14 of the ES5 standard. We've built JSCert using the Coq proof assistant, using the same metaphors and data structures as the ES5 standard, and following ES5 algorithm listings line-by-line. This means we can evolve our formalism along with ECMAScript: local changes to the standard should mean similarly local changes to JSCert. At the same time, we've structured JSCert to make it as easy as possible to build analysis and verification tools on top. We also provide JSRef, an interpreter for ES5, which we have verified in Coq to correctly implement JSCert. We have also tested JSRef using test262. Since each line of JSRef has a close correspondence with a given line of JSCert and the ES5 algorithms we will be able to use code coverage tools to begin to evaluate how much of ES5 is covered by test262. We very much hope that people will be interested in using JSCert and JSRef for investigating, for example, semantics-preserving compilation to ECMAScript, or other language analyses. You can find papers, code, talks and docs all at our website: http://jscert.org The code is here: http://github.com/jscert/jscert And our recent paper describing the project is here: http://www.doc.ic.ac.uk/~gds/jscert_popl14.pdf Thanks, Gareth ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss -- -- Quildreen (Soreλ\a) Motta (http://robotlolita.github.io/http://killdream.github.com/ ) *— JavaScript Alchemist / Minimalist Designer / PLT hobbyist —* ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: ecmascript should support multi-threads
The idea of having shared mutable state in a language is a horrifying one. I'm glad JavaScript isn't heading in that direction. We *do not* need threads for parallelism, and scaling in to use multiple cores. In Browsers, we can already have isolated parallelism through WebWorkers, which means that we can safely use all the cores in a machine without the need of locks, and the possibility of deadlocks. Currently, communicating between these workers is slow because you need to pay the price of serialisation, but they work well for things that don't need to communicate so often. Value classes are planned for ES7, once they're in WebWorkers will be able to efficiently share data between different workers, without the need for locks and the possibility of deadlocks. This is both safer and faster (due to the immutability of the data). As soon as v8 supports Value Classes, Node will be able to leverage then to make parallelism a no-brainer. Until then, the cluster module is the best you'll get. Note that this will also allow us to get the same distributed semantics as Erlang/OTP: isolated processes, crash-only systems with custom supervising strategies. And that's a really awesome thing for writing robust and reliable distributed/parallel systems :) On 12 January 2014 13:59, Andrea Giammarchi andrea.giammar...@gmail.comwrote: if you are talking about node.js there have been recent improvements to the cluster module. I've used cluster even in Cubieboard2 and it works quite well using as many resources as possible if specified. Maybe that won't make JS like Java (thank Gosh!) but combined with linear and async callbacks it does a very good job. http://nodejs.org/api/cluster.html#cluster_cluster Hope this helped, best regards. On Sun, Jan 12, 2014 at 5:26 AM, 紫诡 1511569...@qq.com wrote: hello, now javascript engine don't support multi-threads , because it's nouseful in brower. but, if engine in server, like node.js , it's will be need. although, we can use non-blocking API to do it, but it can't support multi cpu env well good. so , if javascript add SYNCHRONIZED keyword into, and hava Thread Manager API , it will like Java Language ___ 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 -- -- Quildreen (Soreλ\a) Motta (http://robotlolita.github.io/http://killdream.github.com/ ) *— JavaScript Alchemist / Minimalist Designer / PLT hobbyist —* ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Optional Strong Typing
Ressurrecting this thread whoo :) I don't feel static typing making its way to JavaScript. It just wouldn't fit. The core libraries haven't been designed for it, and the community libraries haven't been designated for it. I'd say static typing in JS is a lost cause now. Designing a language for type guarantees takes a far different route than designing a overtly dynamic language — there are plenty of operations in JS whose types that are not even predictable, which often causes JITs to drop optimisations defined for one function or another. However, guards and contracts are cool. They're run-time type checking, and they'll just work with what we have right now. You won't get a Haskell type system, but you'll get confidence about the inputs where it matters. That said, you can still try to shoehorn types in JS by way of an external tool or compile-to-JS language. TypeScript takes this route (Dart too, to a point, but it's a watered-down-Strongtalk-for-teh-web, really). You still won't have Haskell's type system, but you'll have a nice design and documentation tool if you design your type system right. You can't achieve much more than this if you're targeting JS, we can't change the language to being Haskell, or ML, or Scala, since we can't break existing code. To say that types are strictly necessary for large scale applications, is a bit odd, though, and according to some research about effectiveness of type systems, perhaps also incorrect — but I don't remember the name of the papers, and I'm usually skeptical of such papers on CS. On 24 August 2013 08:57, David Bruant bruan...@gmail.com wrote: Le 23/08/2013 19:38, J B a écrit : So the defacto response for large scale JS development will always be: Use X? Even if so, why would it be a big deal? Just to clarify a point, I read interesting definitions of what weak, strong, static and dynamic typing means [1]. Not sure how they are grounded with more formal definitions. Anyway, according to this definition, JavaScript is dynamically strongly typed. I imagine your question is then why can't we have optional static typing in JS?. And I'm not entirely sure what the benefits would be for the entire language. Static typing has huge benefits at development time (early errors, errors more meaningful than undefined is not a function! Had a 5 week experience with TypeScript on a real-life project that'll ship soon. That made a difference). The downside of JS types is that JS engines will have to verify them and that adds to total runtime cost, especially load time, which we don't need to be slower than it is now (something about a 1000ms time to glass barrier [2]). Just to be clear, the main problem isn't JS engines ability to compile JS with optional static type, but more our practice to load too much code (that will have to be verified before running). Hopefully that trend will change, but the web isn't ready to add another static verification step I believe. If the JS engine had knowledge of static types, *maybe* they could go faster (after the slower load time). But how much faster? Current JS engines go really fast after doing type inference when the code is type stable. The interesting part is that the instrumentation/JIT-**compilation costs only for long-running code (and not all the code we've loaded! especially not the unused paths!!), but practice shows that the cost is very small compared to the gains it provides. On a related note, I've recently been asked whether TypeScript compiled more efficient JS (cc'ing Luke Hoban to be sure I'm not spreading misinformation). My answer was that no, it doesn't by itself. TypeScript is very respectful of the input JS (and that's a feature!). However, the JS subset the TypeScript compiler encourages to write to has stable types and has a very strong chance to run faster in current engines. An interesting approach to static typing is asm.js. The interesting part is that the statically compiled part is very localized (and not whole-language-scoped), so its cost is localized. Brendan suggests [3] that ahead of time compilation can only provide better performance. I wonder what's the cost of the static verification is and how much it hurts load time. I'm especially wondering whether this cost will not hurt performance too much when people will load lots of unnecessary asm.js code (cc'ing Dave Herman in case he has answers on that topic), which is obviously not measured by current benchmarks. Anyway, whole-language static typing sounds like a bad idea and use X seems to be to good way forward. The compile-to-JS battle has just started. Let's be patient. David [1] http://coding.**smashingmagazine.com/2013/04/**18/introduction-to-** programming-type-systems/http://coding.smashingmagazine.com/2013/04/18/introduction-to-programming-type-systems/ [2] https://www.youtube.com/watch?**v=Il4swGfTOSMhttps://www.youtube.com/watch?v=Il4swGfTOSM [3]
Re: Proposal: Add functionalities to the for/of protocol that take full advantange of the generators/iterators features
In principle, with functions-as-collections the yield and the whole generators stuff is not needed. If functions can be used on the right of 'in' or 'of' in 'for' then all 'yield' use cases that I saw so far can be implemented without the yield. So why do we need redundant entities? Semi-coroutines for asynchronous computations is one: https://github.com/killdream/promises-benchmark/blob/master/scenarios/serial/co.js#L49-L77 ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: More concise arrow functions
One company I advise tried it, and found that its unsyntax bit back in this way: code that compiled and seemed to do one thing did something quite different. This happens with JS due to ASI; it also happens just due to the C syntax heritage. But it happens more often with CoffeeScript, from what I hear. More of an issue with CoffeeScript's grammar, which is ambiguous in lots of places, and with what I believe to be some bugs in the parser (those Michael Ficarra could probably fix in CoffeeScript redux). I had some examples back in the days I tried CoffeeScript where one-character differences in an object declaration could lead to four entirely different object definitions. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: IIAFEs?
On 1 June 2013 20:52, Jorge jo...@jorgechamorro.com wrote: On 02/06/2013, at 01:22, Brandon Benvie wrote: On 6/1/2013 3:44 PM, Jorge wrote: { block: { if (true) { break block; } } } But then... I'm not sure this is any better than an IIFE! Anything is better than an Immediately Invoked Function-silly-Expression, actually. The only reasonable use for that is to create a new scope in the context of a statement: void function() { doSomething() }() Block scoping/let makes this pattern completely unecessary. As for the other arguments, you do not wrap a function expression in parenthesis, they're already expressions so there's no need for that. At any rate, the problem here is JavaScript's usage of statements instead of Expressions, Expressions Everywhere. e.g.: var x = function(){ return foo }() -- -- Quildreen Sorella Motta (http://killdream.github.com/) *— JavaScript Alchemist / Minimalist Designer / PLT hobbyist —* ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Modules: Curly Free
On 23 April 2013 09:34, Andreas Rossberg rossb...@google.com wrote: On 22 April 2013 17:03, Brendan Eich bren...@mozilla.com wrote: The more convincing argument would be interop with those legacy modules. But the magic for that will be in custom loaders, and AFAICS, the problems (and solutions) will likely be the same in either approach. Yes, custom loaders can interop but as you say, people will have to do something if they want to rewrite to ES6 modules (and Node people may do this soon because they don't have downrev browsers to contend with). When all those (majority share NPM modules) authors rewrite, what should they have to say? it, really? You assume that everybody will just want to transplant their NPM-specific modularity conventions to ES6 unchanged. I don't know if that is true. In any case, I don't expect that default will make them any happier. /Andreas What remains to be seen is whether people writing CommonJS/AMD modules today will want to move to ES6 modules at all ;3 -- -- Quildreen Sorella Motta (http://killdream.github.com/) *— JavaScript Alchemist / Minimalist Designer / PLT hobbyist —* ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Fwd: Modules: Curly Free
On 22 April 2013 09:18, Andreas Rossberg rossb...@google.com wrote: On 21 April 2013 04:15, David Herman dher...@mozilla.com wrote: On Apr 20, 2013, at 5:17 AM, Brendan Eich bren...@mozilla.com wrote: Moreover, ad-hoc seems to suggest some sort of arbitrariness, as if it's not well-motivated. It is in fact well-motivated, by a real requirement that otherwise requires a manual design pattern -- on the part of both the creators *and* the clients of libraries, note well! In fact, I've seen the design pattern arise in practice in other languages. And yet in existing JS module systems, no such pattern is required of a library's clients. (The clients are of course the important case. Yet another instance of the applicability of Mr. Spock's solution!) I'm sorry, but I'm afraid this is one of these moments where I have no idea what the heck you guys are talking about. ;) It is a trivial naming convention, for a single identifier! How is a single name possibly more difficult to learn or remember than any additional piece of syntax, however simple that may be? And how is calling it a manual design pattern less hyperbolic? The fact that explicitly naming things in your modules requires the user to know the internal structure of the module they're dealing with when that isn't exactly necessary adds some complexity (or a manual design pattern). Patterns are nasty, patterns are eugh. At any rate, take these two use cases: First, someone publishes a module that is intended to use as a middleware for processing incoming HTTP requests. Middlewares are just advice functions that wrap around the main handler to do transformations to the request object — they take one function, return a new function. These things are composed using plain old function composition: Say, in Node I have a library that works that way, and I want to process JSON requests and output, which are two different modules. I would use something like this: var json_request = require('json-request-middleware') var json_output = require('json-output-middleware') compose(json_output, json_request)(http_handler)(80) Now, if the modules are required to explicitly name their exports, I'd have to remember what kind of name the author of that module used when I'm really only interested in the module itself (or the middleware it is trying to share with me): import jsonRequestMiddleware from jsonRequestMiddleware import jsonOutputMiddleware from jsonOutputMiddleware compose(jsonOutputMiddleware, jsonRequestMiddleware)(http_handler)(80) So far, so good. Nothing that a good memory (which I don't have, btw) can't deal with. Just a little more of cognitive load can't hurt. Problems arise when you start having a bunch of these modules (and with the Node philosophy that's 99% of the cases) *and* somehow those authors have chosen similar names for their exports. Now you need to remember the name they've used *and* bind it to another name to solve a conflict, when you could just be doing the binding anyways. The second use case would be encoding parametric modules by a single function exports. In this case, you need to unwrap the module anyways before you can use it, because it depends on external stuff that you as the client have to provide. Again, this maps rather straight-forwardly to first-class modules in CommonJS. var dom = require('dom')(cssSelector, eventBridge) dom.query('.foo').on('click', function(ev) { /* event is sanitised here by the eventBridge library */ }) This doesn't map that well to current ES modules because they're second class (unless I've been so out of the loop that I've missed they being promoted): import dom as domFactory var dom = domFactory(cssSelector, eventBridge) Requiring people to name that explicitly creates again unnecessary hops that might be error prone, and deviate from the purposes of the module. IMHO, that does mean things lose a certain clarity, but on the other hand it could be argued that it just forces people to write code using different design choices. This could mean that you fork the community because you can't provide what one expects from a particular module system, and you end up with a messier state than the current CommonJS/AMD/whateverElse. Quildreen Sorella Motta (http://killdream.github.com/) — JavaScript Alchemist / Minimalist Designer — ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Modules: Curly Free
Andreas is suggesting we adopt a convention or design pattern for anonymous exports. Dave is suggesting that it should be supported at the syntax level, so you get language-level guarantees rather than wishful thinking. On 22 April 2013 11:24, Axel Rauschmayer a...@rauschma.de wrote: Andreas Rossberg wrote: Just to be clear, what I suggested was having a single global convention for the name of the 'anonymous' export in every module, say ,it. No need to know the internals of anything. Your Node example, You are imposing a tax on everyone using modules and anonymous export, today a large base of users (modules are predominately anonymous export by counting NPM modules). Is there a way to be explicit about what the tax actually is? Andreas’ convention looks like this: export let it = someValue; import it as foo from foo; If you replace it with default, you *almost* get David Herman’s proposal, which looks like this: export default someValue; import default foo from foo; The advantage of the latter is that you get a static check for syntactic correctness, right? I don’t see any other advantage (but that may be enough of an advantage). Axel -- Dr. Axel Rauschmayer a...@rauschma.de home: rauschma.de twitter: twitter.com/rauschma blog: 2ality.com ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss -- -- Quildreen Sorella Motta (http://killdream.github.com/) — JavaScript Alchemist / Minimalist Designer — ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: 10 biggest JS pitfalls
I'm still amazed to see people rant about other people's perfectly fine coding styles, when those are an overtly subjective matter, and therefore no argumentation on whether Yes ASI or Nay ASI can be right. The only facts about ASI are: 1.) It's a syntax error; 2.) Such syntax error is spec'd to be fixed in a deterministic process — no guessing games here from a grammar POV; 3.) No absolute consensus on whether it's a good or bad feature exists; On the other hand, Python and Haskell programmers seem to be fairly happy with ASI in their languages. I, despite being a Pythonista, actually prefer ECMAScript ASI rules to Python ones, but as Brendan said, more newline significance would solve part of the problem — as in, we'd have rules a bit closer to what Python has. --- As for the list, I'd rather put the implicit errors that might go unnoticed due to scoping/binding warts up there. Clearly calling a function without defining an object should have |this| as Null (fixed) — and it aligns more with the Functional First thingie —, and assigning to undeclared vars in the current or upper-scopes should throw an error rather than create a new property in the global object. On 31 December 2012 15:47, Jorge Chamorro jo...@jorgechamorro.com wrote: On 31/12/2012, at 15:55, Juan Ignacio Dopazo wrote: I'm surprised not to see Automatic Semicolon Insertion in the list. Yes I would ditch ASI altogether if only to force the javascrhipsters to put back each and every semicolon where it belongs: they are *delimiters*. No ASI would force them to stop writing in those silly -and ugly- dialects in which every now and then lines *begin* with a semicolon... As JS compiler *wants* semicolons as delimiters, instead of attempting to guess and fix buggy src code via A.S.I. which often results in failure anyway (even silent failures which is worse), it should better halt and complain loudly about syntax errors. IOW, Javascrhipster's style code is nothing but a big multi line syntax error, fixed by ASI. Happy new year! -- Jorge. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss -- -- Quildreen Sorella Motta (http://killdream.github.com/) — JavaScript Alchemist / Minimalist Designer — ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array#sort(prop)
On 01/04/12 18:49, Peter van der Zee wrote: No idea whether this has been discussed before, but I find myself continuously doing this when sorting arrays with objects: arr.sort(function(a,b){ if (a.prop b.prop) return -1; if (a.prop b.prop) return 1; return 0; }); Couldn't we add an optional string argument to Array#sort that does this for us? If supplied do the above, otherwise behave as usual. If there's already a first arg planned for .sort (I haven't kept up), make it the second arg. arr.sort('prop'); I believe this would be better left for a higher-order helper function, given the sort function already receives a predicate: function compareProperty(name) { return function(a, b){ return a[name] b[name]? -1 : a[name] !== b[name]? 1 : /* otherwise */ 0 }} arr.sort(compareProperty('prop')) So, this keeps the `sort' function's semantics simple and straight-forward. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: arrow function syntax simplified
On 01/04/12 15:08, Allen Wirfs-Brock wrote: On Apr 1, 2012, at 8:07 AM, Quildreen Motta wrote: How is the above better (ignoring any controversy about line-beginning separators) than: let ps = { lookahead ( n) { this.current().slice(0, n || 1) }, current() { this.text.slice(this.offset) }, move(n) { this.clone(this.text, this.offset + 1) }, clone(text, offset) { let r = Object.create(this); r.offset = offset || 0; r.text = text || ''; } } I forgot the object literal syntax was also getting a lightweight method definition syntax, my bad. You'd perhaps avoid some of the confusion on dynamic `this' by making it explicit that `this' is just an additional parameter passed over to the function — albeit implicitly. this isn't just an additional parameter and trying to turn it into such just creates more confusions. this (aka self) is a characteristic feature of object-oriented /methods/, not of functions. Methods only have meaning in the context of an object. It is essential to the OO programming model that this/self is dynamically bounds to the object that is the target of each method invocation. In a well designed OO language the method invocation target is syntactically distinct from other parameters. If this didn't have special OO semantics there would be no reason to have special syntax and semantics for defining/accessing this within a function. However, in that case you don't have a OO language, instead you have a functional language that is used to provide a (low fidelity) simulation of OO constructs. Hm, perhaps because of my mostly functional background — JS is the only OO language I've actually spent much time learning, — I've always seen methods as higher-order functions (target - a... - b), and the `object.method()' invocation pattern as just coupling single dispatching with a nice infix function invocation syntax. Maybe I'm thinking more in terms of possible implementation details than concepts, which I'm not as familiar with. It seems to work for Python, though there `self' is bound at the instantiation time. I don't believe this is correct, if you mean object instantiation time. You can view obj.meth in Python as a left-curry operation that creates a new function where the first parameter of meth is pre-bound to obj. This is why Python does not have issue 3 above. Ah, yes, you're right. The currying is done at the lookup/dispatch time. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Let's replace | with :: (was Breaking up the |...)
On 03/17/2012 01:55 PM, François REMY wrote: Wouldn't it be better to use 'as' for guards? Seems more intuitive and easier to type let A as Number = 3; let B as Email = x...@google.com; class ListNode { public nextNode as ListNode; public value; // no guard } However, it is'nt a reserved keyword. But I don't think anybody sane would use 'as' as a variable name. Additionnaly, we could also require 'use guards' like we are going to require 'use fn'. I'm pretty sure most mainly Haskell programmers doing JS would think about using `as' (and `bs', `cs', ..., `xs') as identifiers almost naturally. And I guess they would also feel it natural to use `::' for guards. But well, this is not Haskell :3 ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: How about replacing | with -
On 03/04/2012 02:14 PM, Allen Wirfs-Brock wrote: On Mar 3, 2012, at 11:17 PM, Brendan Eich wrote: Dean Landolt wrote: Does it /have/ to be ascii? Does it have to be grawlix? [snip...] I have two significant sized code samples that differ only in the use of beget in place of | Compare: https://github.com/allenwb/ESnext-experiments/blob/master/ST80collections-exp1.js and https://github.com/allenwb/ESnext-experiments/blob/master/ST80collections-exp6.js Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss My major problem with a spelt out operator is that it gets difficult to tell it from the surrounding words at a glance. Though it gets a little better if one has some sort of syntax highlighting support, the symbols are just easier to spot in the code, which gives you the ability to just glance at related pieces of code (for those who abuse editors like Emacs for side-by-side views of the code, like me) and tell the relationships between those objects. It's just that with a spelt out operator you actually have to read the whole line. About the choice of a word operator vs a symbol operator based on whether the programmers are native English speaker or not, I don't think it would make much of a difference. I did have my concerns at first as well, but I haven't felt any additional cognitive load to remember either, so I think they both impose about the same amount of additional learning for a programmer that is unfamiliar with the additions in Harmony. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: How about replacing | with -
On 03/04/2012 03:38 PM, Gavin Barraclough wrote: On Mar 3, 2012, at 11:17 PM, Brendan Eich wrote: Does it have to be grawlix? I proposed let sub = sup beget {p:1, q:2, r:3}; +1. Using a symbol like an arrow makes a lot of sense when there is a clear directionality in the operation (e.g. chasing a chain of pointers in C), but the lack of consensus as to which direction the arrow should point in seems likely to be indicative of a larger problem - that either choice is going to be backwards, unintuitive, and confusing for a significant proportion the users. The operation of prototypical inheritance, as implemented by JavaScript, has a clear direction, though. It's just a delegation from an object to a prototype, thus: `super | (or :, or ~, or ...) { p: 1, q: 2, r: 3 }' makes sense. With `super - { p:1, q: 2, r: 3 }', it could be argued that the operation as super is the delegation for the object, although I find it slightly counter intuitive, since property lookup starts at the base object and goes all the way up to the prototype chain (as an arrow pointing to the left would suggest). ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: How about replacing | with -
I find the syntax `proto - object' counter-intuitive. Anytime I think about prototype delegation, the semantics are clear that an object `X' delegates to a prototype `Y'. This semantics don't map well in `proto - object', instead you have something more along the lines `proto is the basis of object', although the first thing that comes to mind is still `proto maps to object'. And yes, this is a nitpick. On the other hand, there are strong associations of such a symbol with different semantics in other languages, property access and function shorthands being the most common. I'm not sure introducing a symbol that's been used for entirely different semantics in the majority of other languages is a good idea, and would bring more confusion. - sounds too much like return (local or not). So, at this point I still think `lhs | rhs' is the best alternative in syntax, as it lends itself easily to the `rhs delegates to lhs', which is the core semantics of a delegative prototype implementation. On 03/02/2012 07:30 PM, Allen Wirfs-Brock wrote: It was recently suggested to me that it is unlikely that we will ever adopt - as as function expression shorthand symbol and that this means we could consider using that symbol sequence for other purposes. In particular, it would be a reasonable and possibly less controversial alternative to the | symbol. I would have no objection to that switch and have written the suggestion up at http://wiki.ecmascript.org/doku.php#suggestion_to_replace_with Some examples of this usage of - include: MyObject.prototype - {a:1,b:2} appArrayBehavior-[0,1,2,3,4,5] let subclass = superclass - function () {}; var p = newRegExpMethods - /[a-m][3-7]/ What do you think? Do you like - better than | ? Is it ok to not have it available for some possible future function shorthand? Allen ___ 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: How about replacing | with -
I find the syntax `proto - object' counter-intuitive. Anytime I think about prototype delegation, the semantics are clear that an object `X' delegates to a prototype `Y'. This semantics don't map well in `proto - object', instead you have something more along the lines `proto is the basis of object', although the first thing that comes to mind is still `proto maps to object'. And yes, this is a nitpick. On the other hand, there are strong associations of such a symbol with different semantics in other languages, property access and function shorthands being the most common. I'm not sure introducing a symbol that's been used for entirely different semantics in the majority of other languages is a good idea, and would bring more confusion. - sounds too much like return (local or not). So, at this point I still think `lhs | rhs' is the best alternative in syntax, as it lends itself easily to the `rhs delegates to lhs', which is the core semantics of a delegative prototype implementation. On 03/02/2012 07:30 PM, Allen Wirfs-Brock wrote: It was recently suggested to me that it is unlikely that we will ever adopt - as as function expression shorthand symbol and that this means we could consider using that symbol sequence for other purposes. In particular, it would be a reasonable and possibly less controversial alternative to the | symbol. I would have no objection to that switch and have written the suggestion up at http://wiki.ecmascript.org/doku.php#suggestion_to_replace_with Some examples of this usage of - include: MyObject.prototype - {a:1,b:2} appArrayBehavior-[0,1,2,3,4,5] let subclass = superclass - function () {}; var p = newRegExpMethods - /[a-m][3-7]/ What do you think? Do you like - better than | ? Is it ok to not have it available for some possible future function shorthand? Allen ___ 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: Block lambda is cool, its syntax isn't
I have an obvious bias towards 1 because I think Unicode symbols describe much better the underlying intentions and semantics than their ASCII alternatives (usually), however not many people creates mappings for these symbols on their .XCompose (or even have a compose key handy). I remember you mentioning that the Haskell-ish alternative `\x, y { body }' or `.\x, y { body }' was not practical, because \ is already a valid escaping character in identifiers (?) Given those above, despite my usual disliking of Ruby syntax, I prefer the pipes over parenthesis, given the latter has an already too overloaded semantics, such that `{ (foo, bar) (2) }' would look pretty confusing, at least to me. However, what about `{x, y: body}'? Granted we don't allow labels immediately following a lambda block (and I'm not sure labels are used much in the language, I could be wrong however). 2012/1/13 Brendan Eich bren...@mozilla.org: We have three coarse-grained alternatives: 1. λ (params) { body } 1a. One problem is what should we use for λ? 'lambda', 'block', etc. are not reserved the syntax. Whatever the identifier (including Greek lambda: λ), this is an incompatible change. 1b. Another problem: this form looks like a function expression with a different introductory keyword, but Tennent's Correspondence Principle makes the meaning of body elements including |this| and return/break/continue radically different. Different-enough semantics should have different syntax. 2. { (params) body } Putting the parameter list in parentheses is more consistent with function syntax, while putting the parameters on the inside stresses the block-ness over function-ness. By block-ness I mean (ignoring let, const, and function in Harmony) how code and {code} are equivalent. Of course this cuts against the syntax too: block statements are not first-class callables whose code bodies are evaluated only if invoked, they are statements evaluated eagerly when reached. This syntax is arguably too block-like. A point that I remember having come up in past TC39 meetings: if we ever want structuring forms (object literals or destructuring patterns) that use () for grouping property names, this syntax is future hostile. 3. { |params| body } This is new-to-JS, idiomatic block-like -- but not too block-statement-like -- syntax for novel body semantics. The bars will drive some people to distraction. Others will grok, or already do via Ruby. This is not to favor Ruby, just to build on the belief that some precedent in language design is better than none. We could reject (3) in favor of (2) if we had an overriding non-aesthetic reason. I don't see one. Aesthetics vary. The more conventional look of (2) seems like a usability hazard to me, which trumps aesthetics. Again I'd rather have something more different-looking to signal the novel application of TCP. /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: Alternative syntax for |
2011/11/22 Bob Nystrom rnyst...@google.com On Tue, Nov 22, 2011 at 10:41 AM, Brendan Eich bren...@mozilla.comwrote: Nothing there about arrays or regular expressions, and the function examples do *not* show anything like superFun | function (...) {...} Instead of Ahem'ing, could you cite what you claim is a prior proposal with specifics showing how it addresses object, array, regexp and function [[Prototype]] presetting? I'm guessing this been proposed before but I think you could handle all of those except RegExp with syntax something like: // object: { extends someObj, prop1: value, prop2: value } // array: [ extends someObj, value1, value2 ] // function declaration: function foo(arg) extends someObj { ... } // function expression: function(arg) extends someObj { ... } You could *maybe* cram it into RegExp with something like: /pattern/ extends someObj; I haven't been following the | discussion closely (it seems like it's in good hands and has lots of smart people poking at it) so forgive me if this was proposed and rejected for valid reasons while I wasn't looking. :) From what I get of Claus' proposal, this is more or less what he's been proposing. Though he seemed to be proposing it from a type-decl/declarative stand point: type X :: JSObject (Proto proto) thing to be roughy equivalent to `proto | thing'. which would be in turn roughly equivalent to the imperative form: thing = {} | /regex/ | function(){ } | [] | 1 | a // - don't mind my lazyness and treat this as several different kinds of possible objects in the next statement thing.[[prototype]] = proto So, the | syntax would be a declarative form that composes something of the type in the RHS, having a prototype as LHS, thus working for any kind of object -- just as __proto__ does. Then he proposed using the same syntax for doing pattern matching on the prototype chain, which sounds quite cool. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: motivating | as structure representation, not operator
On 19/11/11 13:42, Axel Rauschmayer wrote: (I'm thinking about blog posts here, which typically face the dilemma of talking about [[prototype]] vs 'prototype', to help readers in the long run while confusing them at first, or talking about __proto__, to be understood in the short run, with possible problems later). Where human language usually fails me is when I initially explain prototypes in the __proto__ (or Object.create() or Self-ish) manner and then get to constructors. Then I talk about the constructor’s prototype to avoid the longish “the value of the prototype property of the constructor”. But that’s confusing! It’ll get worse should constructors become prototypes of each other in the future. Constructors are really the only confusing thing in JavaScript's prototypical implementation. The way I usually explain it is by first talking about `[[Prototype]]' and the under-the-hood semantics using objects alone, then explaining how constructors mess all that up :3 The special-casing of `new' has been my favourite topic so far. That said, I find it interesting to think about | in terms of structural notation rather than yet another complex layer on top of constructors. In fact, I'd rather give up on constructors entirely, but I don't think that's an option now =/ ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Minimalist (why) classes ?
On 12/11/11 19:07, John J Barton wrote: This kind of discussion illustrates my point: JS is not sweet enough because we are missing core operations for constructing prototypes in a standard way. Agreed. I've always thought about JS objects as sets, but it feels weird that I don't get disjunction, intersection and other basic operations out of the box. Basically, I've missed primitives for: - Creating objects that share properties from other objects (Object.create) - Adding properties to an object (Object.extend) Object.extend(Object target, Object sources...) → Object (sources.reduce({|tgt, src| Object.keys(src).forEach({|key| tgt[key] = src[key]}) tgt }, target) Should `extend' copy all the properties? Only the own properties? I feel `own' properties make more sense. - Defining new objects that extends on the [[Prototype]], which is basically Object.create followed by copying the properties of one or more objects over to the new instance. (Object.clone? Object.inherit? I never felt `extend' quite says it all) Object.prototype.clone(Object parent, Object mixins...) → Object (Object.extend.apply(Object.create(parent), mixins)) - Merging (while possibly flattening, as objects can't have several [[Prototype]]s) objects. Object.merge(Object mixins...) → Object (x = Object.extend.apply({}, mixins)) Dicts are probably a better answer for this one though. - Creating instances from objects directly (new Stuff, Stuff.new), though I'm not sure there's much sense in having two different standard ways of doing the same thing. I guess JS is stuck with constructors =/ - Creating objects by removing/renaming certain properties from other objects, which is useful for object composition. Though I guess this would be handled by traits(?) Of course, you still need a better syntax to express it all, and the proposed extensions to object literals come close to minimalist classes: var foo = Base.clone({ method1() { }, method2() { }, get stuff() { } }) var foo = Base | { method1() { }, method2() { }, get stuff() { } } class foo extends Base { method1() { } method2() { } get stuff() { } } That is, if we disregard private and other modifiers. If such modifiers were added to the Object literal (meh?), it would be quite the same thing. Except a full-blown declarative class syntax could be better optimised and would allow for a sugary syntax if/when traits/type guards are added. var foo = Base | { #constant: 1, // or const @private_stuff: bar, // or private method1() { }, method2() { } get stuff() { } } class foo extends Base { @private_stuff: bar; // or private #constant: 1; // or const method1() { } method2() { } get stuff() { } } Except I'm not sure the @private could be made to work without creating confusing semantics around it, so object literals would still be one step behind. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Minimalist (why) classes ?
On 11/11/11 23:44, John J Barton wrote: On Fri, Nov 11, 2011 at 4:48 PM, Brendan Eichbren...@mozilla.com wrote: On Nov 11, 2011, at 4:42 PM, John J Barton wrote: Object.extend() does not exist. Which one do you mean? I mean Object.extend does not exist. Irakli is using Function.prototype.extend, not something like PrototypeJS's Object.extend. Iraki wrote Object.extend(). `Object' is a function, though. So it shares stuff from the Function.prototype object :3 ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: making |this| an error (was Re: for own(...) loop)
2011/11/9 John J Barton johnjbar...@johnjbarton.com I'm sure this has been discussed before, but isn't is possible and desirable to make |this| illegal in using strict; when it can be determined from the AST alone that |this| will bind to |window|? eg: Object.keys(foo).forEach(function(key) { // this is undefined- window }); This case kind of case is because, as others have noted, incorrect |this| binding most often occurs in two cases: 1) mixed OO and functional programming (as above) and 2) callback defn. In `strict-mode', |this| would resolve to `undefined' inside that function anyways. I'm not a fan of making constructs illegal just because their semantics might be confusing, even more so when such disallowance would vary highly in context. It would be bound to make things more confusing, imho. Block lambdas are the best solution I can see right now. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: for own(...) loop (spin-off from Re: for..in, hasOwnProperty(), and inheritance)
On 08/11/11 18:49, Brendan Eich wrote: The recommended practice when writing for-in loops in JS today is to write: for (i in o) { if (o.hasOwnProperty(i)) { /body/ } } Although many JS developers do not follow the recommendation (out of ignorance or intentionally, doesn't matter). Should ES.next provide sugar for the recommended pattern? To make it compose with declarations and destructuring in the for head, it should use a contextual keyword immediately after 'for': for own (i in o) { /body/ } This is a small thing but it might pay off in the long run. Isn't that just: Object.keys(o).forEach(function(i){ body }) Iirc, that's faster than a for..in loop with filter in v8 due to the aggressive function inlining, not sure about SpiderMonkey. It also reads better and it's more composable -- for me, at least. I do use keep `var keys = Object.keys' and other hand aliases though. It still seems to me it's overkill to add special syntax (and a new reserved word, yuck!) to something that isn't really worth it, given the Object API already provides those methods. Also, are Object.values and Object.items standardised in ES.next. They're quite useful? /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: for own(...) loop (spin-off from Re: for..in, hasOwnProperty(), and inheritance)
On 08/11/11 19:19, Axel Rauschmayer wrote: I see two domains for the concept of “own” properties: 1. Meta-programming. Could you expand on the use of `own' properties for meta-programming? I'm afraid I can't really envision it =/ 2. Using objects as dictionaries. Isn’t #2 the majority (at least as far as non-library-programmers are concerned)? Will the concept become less relevant once we have David Herman’s dicts? I would think most of the cases where objects are used as dicts would be solved by using `Object.create(null)', today on ES5-compliant engines. Except for the nasty, nasty `__proto__' on engines that use that magic, but then you can proxy property access/assignment. It's quite ad-hoc, but works. The dicts proposal looks nice though. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: for own(...) loop (spin-off from Re: for..in, hasOwnProperty(), and inheritance)
On 08/11/11 20:22, Axel Rauschmayer wrote: I see two domains for the concept of “own” properties: 1. Meta-programming. Could you expand on the use of `own' properties for meta-programming? I'm afraid I can't really envision it =/ Whenever you copy properties from one object to another one, you are usually doing meta-programming (unless you use an object as a dictionary). Hm, I see. I always tend to think of meta-programming in the Lisp sense (macros that mutate the AST), but I guess I see the point in generating objects dynamically. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: for own(...) loop (spin-off from Re: for..in, hasOwnProperty(), and inheritance)
On 08/11/11 21:36, Brendan Eich wrote: Ignoring performance, a lot of stylish JS hackers use Object.keys(o).forEach. How many run into the wrong |this| (arguments/break/continue/return)? Not clear. Something to study. Well, I use Object.keys, etc, a lot thorough my code. I can't remember a case where I forgot to pass the `thisObject' parameter to the `forEach'/`map' call in the last months, though it was weird when I transitioned to a more functional coding style. I guess the number of cases I was bitten by the wrong |this| in the beginning is about the same number of ASI issues I ran into when I started using destructuring assignments for arrays. I'd assume that has a lot to do with coding habits — writing without properly thinking. `reduce' and `reduceRight' don't have a `thisObject' argument. Why are they the only odd ones? ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: for own(...) loop (spin-off from Re: for..in, hasOwnProperty(), and inheritance)
On 08/11/11 23:59, Jake Verbaten wrote: However on average a lot more people will use for ... in with hasOwnProperty because ES5 environments are rare and a lot of people avoid the ES5-shim Do you mean `rare' as in they have to work with the lowest common denominator (IE)? Because ES5-not-so-fully-but-somewhat-there-for-most-common-stuff environments are the majority, afaik. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Loyal Opposition to Const, Private, Freeze, Non-Configurable, Non-Writable...
I think Claus summarizes nicely what I've been thinking about this thread, and the opposition-for-the-sake-of-opposition that has been spreading through the JavaScript community. Though most of that seems to be based on JavaScript should be kept simple. I'd argue there doesn't need to be conflicts between expressivity and simplicity. Remember, your concepts of expressivity might not be the same as my concepts of expressivity, just as the way you approach a certain problem might not be the same as the way person B and C approach a certain problem. And given that the methods to solve a problem doesn't immediately qualify something as bad or wrong, if we can reach a common ground on what group A needs for expressing their ideas, and what group B needs for expressing their ideas, why shouldn't we? It's only a problem if said features clearly reduce the expressivity of the language for a certain group of users considerably (and that's when you should say it does, so people working in the language can do better iterations on the particular feature design), and I don't see it as being the case for const, private or frozen objects, tbh. JavaScript is a huge language, it's used by several people, and used to solve several kinds of problems. Different problems need different features, they need better syntax too -- that's why DSLs are lovely, and why people keep creating them even though you could just as well write everything in C. So, if instead of making a language one-size-fits-all that's geared towards solving only a particular problem well, if we can give people different flavours of the language by features that don't conflict, or don't make the language a pain to everyone else, I think that's something worth seeking. Of course, we can't please everyone -- and I'm not saying we should, -- after all, languages are inherently biased. But that doesn't mean we can't give people better tools for solving new problems. Isn't that what programming is all about, anyways? :3 2011/11/3 Claus Reinke claus.rei...@talk21.com I'm not just talking about implementors, either. Some users will want to know d.m isn't going to change. They may not want to know that it's b.m, mind you -- they simply won't want that c.m assignment to be legal, or else if they do support such a thing, they don't want it to affect d's vtable. I would argue that developers who rely on these kinds of assurances are actually slowing down their own, and others, productivity. Assuming they wrote the perfect method and it should never be changed is a grand claim for anyone who isn't Donald Knuth. Assuming that the consumer of their code is responsible for their own bugs if they introduce them with monkey patching class methods seems fair. Ok, I have to wade in here: if you cannot see why some people want such features, why are you arguing against these features? [the you here is not (exclusively) about you, but about a pattern often exhibited by vocal and repeated opposition to things:-)] The Javascript user base is huge, with obviously different views, and this doesn't seem to be your discussion to have, does it? You could try to argue that warnings are better to have than errors in Javascript, eg, it should be easy to spot if someone is interfering with your code's base assumptions, but you don't want that to stop you from running that code anyway, knowing that doing so might be unsafe. Example: the switch from warnings to errors for non-essential features of JSLint meant that many JS coders can no longer use JSLint, so the switch actually reduced its effectiveness. So, if a proposed feature interferes with your use of the language, state that interference, and perhaps the proposals can be changed to accommodate your concerns. That is a discussion based on technical issues, which can make progress and can achieve targets. However, you might consider how your personal perspective affects your judgement: - if you're developing node, you're at the start of the chain, no-one can interfere with your definitions - if you're developing node libraries, you have to keep up with node only, but you have to do that anyway - if you're using libraries from a single source only, you're still not likely to be affected, because those libraries are either consistent or have a bug that needs fixing - if you're using libraries from several sources, you'resuddenly open to a lot of trouble, as any library from source A might interfere with base assumptions made by any library from source B - if you're browsing the web, where many pages include code from dozens of sources, you're out of luck quickly if you cannot see what is conflicting with what - if you're in the business of trying to ensure that webusers won't run into trouble, you want to pin down what each page widget and ad module is allowed to do (whitelisting); and if you take that to its conclusion, you need to base your
Re: Minimalist Classes
On 02/11/11 11:01, Erik Corry wrote: 2011/11/2 Axel Rauschmayera...@rauschma.de: super Foo.bar(x) should desugar to Foo.prototype.bar.call(this, x) http://wiki.ecmascript.org/doku.php?id=harmony:object_initialiser_super What is that you don’t like about Allen’s proposal? You are still hard-coding the name of the super-constructor (which is what `super` nicely avoids). lookup starts with the object that is the prototype of the object defined by the object literal that contains the reference to super. So it only works inside an object literal, whereas mine is easier to understand and works anywhere. If you are using it without any of the other stuff you can even trivially get your minifier to desugar for older browsers. I don't think hard coding the name of the super-constructor is a problem. It is when you take into account that functions in JavaScript are not bound to an object, they are generic. You can simply assign any function to any object and it'll most likely just work. So, what I mean is that, if you have `super' resolve to a hard-coded constructor name this is what you get (hell, I don't even use constructors anymore, those ugly, ugly things): --- function Thing(name) { this.name = name } Thing.prototype.describe = function(){ console.log('A thing ' + this.name) } function Subject(name) { super.constructor(name) } Subject.prototype = Object.create(Thing.prototype) Subject.prototype.constructor = Subject Subject.prototype.describe = function() { super.describe() console.log('A subject ' + this.name) } // For now, all is well, `super' in Subject will always resolve to Thing. var car = new Subject('car') car.describe() // = 'A thing car' // = 'A subject car' // But remember that you can take any function and assign to any object // Such that the following wouldn't work -- we want Teddy to be just // a Subject here, not a Thing. var teddy = { name: 'teddy', describe: Subject.describe } teddy.describe() // = 'A subject teddy' // = 'A thing teddy'. // Whereas with Allen's proposal, everything would work okay: var teddy = { name: 'teddy' } // The defineMethod call creates a new function `describe' that // has its |super| reference bound to teddy's prototype Object.defineMethod(teddy, 'describe', Subject.describe) // And the new `describe' function can use this static |super| to // determine where lookup starts teddy.describe() // = 'A subject teddy' --- Of course, applying a function to another object is a different matter, which won't be solved by static super. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Minimalist Classes
On 02/11/11 13:01, David Bruant wrote: Le 02/11/2011 14:26, Jeremy Ashkenas a écrit : (Full Disclosure: I'm still very opposed to const, private, and their object-lockdown friends, ) Regarding const, it's an optional keyword basically telling the interpreter hey, the value isn't suppose to change at runtime, please ensure it!. It prevents bugs of mistakenly redefining something that shouldn't be redefined. Why are you opposed to this? Yeah, immutability and referential transparency are wonderful things. I wish JavaScript developers would rely more on it, it makes things saner to work with. Though is `const' the same as Object.freeze(thing) when `thing' is an object? Or does it just ensure that the slot in the object isn't reassigned? Regarding private, I'm puzzled. Having private attributes in objects is necessary to implement encapsulation and get all the benefits of good object-oriented practices. I still think `private' is quite overrated. It gets terrible if you want to test something and the developer went through all the trouble of making proxies to access everything, as well as making everything stateful. That said, there are some valid use-cases for it... I guess? ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Loyal Opposition to Const, Private, Freeze, Non-Configurable, Non-Writable...
On 02/11/11 14:05, Jeremy Ashkenas wrote: On Wed, Nov 2, 2011 at 11:01 AM, David Bruant bruan...@gmail.com mailto:bruan...@gmail.com wrote: Could you elaborate on this point? All object-lockdown I can think (non-configurability, non-writability, non-enumerability, private names, const variables, const classes) of is optional. Why are you against them? I was about to say if you're unsatisfied, create a language which doesn't provide features you don't like, like Coffeescript, but... humm... So, why being against the introduction of features in the language? I'd be glad to elaborate -- but since it's off topic for minimal classes, changing the Subject here. What draws people to dynamic languages is freedom. I'd put `extensibility' and `expressivity' here instead, but sure. And JavaScript does pretty good at that --- not as much as Lisp, but oh well, it's not like I expected a C-family language to be that extensible :3 If I had my druthers, JS.next would generally embrace the spirit of JavaScript's dynamism (and freedom), and try to push those aspects further -- with better introspection and more flexibility -- instead of compromising with more restrictive static languages and adding lock-down keywords so that some programmers might feel safer. Agreed. But there are other things here other than security constraints. private does not add anything new to a property. If you don't want the property to be used outside of the class ... don't use the property outside of the class. I still haven't found an use to private either, to be honest. Granted I often declare private functions and variables inside a closure, I always export them in an `internal' object, so it doesn't clutter the core API. const does not add anything new to a variable. If you don't want to change the value of a variable ... don't change the value of the variable. I'm not sure I agree here. Constants are not about security they're about abstractions. You name something that you'd otherwise have to write as a regular expression. In this case, they'd be like a really simple inline function, except they do no transformations. freeze does not add anything new to an object. If you don't want to change the shape of an object ... don't change the shape of the object. Again, immutability isn't just about security, but optimisation as well. You could also look at shared-memory threads, because I think they make a hell of an argument for frozen objects or immutability. JavaScript should be about making it easier to write the right thing, and not so much about making it harder to do the wrong thing. After all, the former is purely positive, and the latter assumes that you know better than the engineer who comes after you. In the real world, you often don't. Agreed, but note that none of the features above preclude JavaScript from being a free language that makes it easier to write the right thing. It'll be just as expressive as before. Also note that you can already achieve all of those functionality in current JavaScript, so having class-literals, as a declarative syntax, support them in a nice way is okay. It's not like any feature can't be abused as you say. But the fact that a feature can be abused doesn't mean it should be never considered. JavaScript's `with' is a good example of that. You could create the most awesome and expressive module library using that, but no vendors have optimized it (as far as I know) because people considered it could only ever be abused and haven't used it. Also, note that `with' makes a whole awesome use-case for `Object.freeze': --- with (require({'library1': 'lib1'}, {'library2': 'lib2'})) { lib1.foo(lib2.something) } // Would be equivalent to Python's // import library1 as lib1 // import library2 as lib2 // // But restricted to a block. --- You could also use it as a dynamic let, and just as long as you freeze the object passed to `with', there's no reason one shouldn't optimize it as just a regular EnvironmentRecord lookup. Using `let' instead of `var' removes the thing about variable hoisting declaring the variable outside of the `with' scope, etc. tl;dr; While `private', `const' and `freeze' could certainly be abused, that doesn't mean they don't have value... well, perhaps except for `private'. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Loyal Opposition to Const, Private, Freeze, Non-Configurable, Non-Writable...
On 02/11/11 14:26, John J Barton wrote: Another maybe stronger argument is simplicity: these myriad new minor features create a blizzard of chaff in the way of developers. One excellent example is Object.create(). Here was a terrific opportunity to simplify the language based on years of experience and analysis. But instead of an object as a second argument, we got a descriptor requiring many details for each property. Of course these details are important for the use-cases that need them. Unfortunately everyone else has to carry the baggage. `Object.create' is not supposed to be used directly by end-users. It's for library writers. Library writers get the heavy weight and generic things, and transform that for a specific use-case. Of course, not having an `Object.extend' and other object composition functionality makes things a little too meh. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Loyal Opposition to Const, Private, Freeze, Non-Configurable, Non-Writable...
On 02/11/11 15:41, Brendan Eich wrote: On Nov 2, 2011, at 9:26 AM, John J Barton wrote: Of course these details are important for the use-cases that need them. Unfortunately everyone else has to carry the baggage. What exactly do you mean by carry? Implementors have to implement. They get the big bucks and bear the burden for the greater good. Most users *do not* have to carry all the ES5 APIs in their head. Almost no users ever even need to use Object.create. Perhaps this is a missed opportunity, but that's a different argument from what your use of carry implies. Imho, no users *SHOULD* use Object.create directly. That's why abstractions exist — and first class functions make it easy enough to make them. Also, there are plenty of libraries provide nice abstractions over the low-level part of the language (pd being the simplest one, I guess), to a point I think criticising a built-in feature for being too generic is kind of missing the point... It's been this way with the DOOM too, isn't it? ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Minimalist Classes
On 02/11/11 15:42, Erik Corry wrote: 2011/11/2 Quildreen Mottaquildr...@gmail.com: I don't think hard coding the name of the super-constructor is a problem. It is when you take into account that functions in JavaScript are not bound to an object, they are generic. You can simply assign any function to any object and it'll most likely just work. I think the chances are slim that you can take a function that does a super call, put it on a different object, and it will 'just work'. It's a pretty rare case. most likely. Also, it should work if |super| were dynamically resolved, as long as the object implemented what's required by the call. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Loyal Opposition to Const, Private, Freeze, Non-Configurable, Non-Writable...
On 02/11/11 15:49, Brendan Eich wrote: On Nov 2, 2011, at 9:30 AM, Quildreen Motta wrote: Also, note that `with' makes a whole awesome use-case for `Object.freeze': 'with' is gone in ES5 strict, ES6, and beyond -- you knew that, right? Yep, and I still think it's a sad thing. Not that I use it anyways, the performance doesn't allow me to. And we're getting real `let'. --- with (require({'library1': 'lib1'}, {'library2': 'lib2'})) { lib1.foo(lib2.something) } This is still hard to optimize, even with the implied freeze under require. Hm, not sure I understand why. I'm not a compiler writer though. Also, you can't load code dynamically without nesting an event loop and violating run-to-completion, so I'm not sure how such a require would work. Yes, but `require' could take a plain object out of a map or something, it could use a synchronous call. But I don't think that matters much here :3 This does remind me: JS's freedom is Dart's cannot be tooled and inherent performance problems, and without aggressive optimization work it can mean JS is measurably slower for some kinds of code than Dart (or Java). (cannot be tooled is flat wrong, as past discussion here of static+dynamic/live-system analysis concluded.) To inherent performance problems, I say feature and optimize harder. But it's worth mentioning, especially since you cited 'with', which is a bug that I brought ;-). Stupid-dynamic is just stupid and we should avoid it. Freedom without fences and other tools for accountability fails at scale. I still don't agree with `with' being a failure (perhaps the syntax ended up too ambiguous, yeah, and the thing about being able to change the shape of the objects and all, but...), I agree with the optimise harder though. I wonder if it was the Racket guys who said that languages should indeed be dynamic, so compiler writers have more work to do :3 ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Minimalist Classes
On 02/11/11 16:21, Brendan Eich wrote: On Nov 2, 2011, at 10:52 AM, Quildreen Motta wrote: On 02/11/11 15:42, Erik Corry wrote: 2011/11/2 Quildreen Mottaquildr...@gmail.com: I don't think hard coding the name of the super-constructor is a problem. It is when you take into account that functions in JavaScript are not bound to an object, they are generic. You can simply assign any function to any object and it'll most likely just work. I think the chances are slim that you can take a function that does a super call, put it on a different object, and it will 'just work'. It's a pretty rare case. most likely. Also, it should work if |super| were dynamically resolved, as long as the object implemented what's required by the call. We can't do dynamic super without adding a parameter to every function call everywhere (modulo optimization), or simulating Algolish nested scopes using dynamic scope hacks, or worse. This is something we won't do, I'm pretty sure Erik agrees. Ah yeah, I'm well aware that dynamic super isn't happening. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Minimalist Classes
While the class literal proposed by Jeremy is indeed nice, I think it misses the point of *why* class literals are desirable. What you've proposed can already be achieved, with the same sugar -- and without introducing a new construct, so people using ES3 can also get it through a library, etc -- by using object exemplars: Selfish, Prototoypes As Classes, etc. The e-mail Erik pointed has got most of it, though what I really think class literals can bring in that makes them worth is a better and declarative syntax for private/const members and traits. Static shape can be achieved through `Object.freeze', right? I don't think that should be what classes strive to provide. Yeah, static analysis is nice and all, but I believe that goes against the nature of the language's own semantics, and if classes are supposed to be just sugar over prototypical inheritance (with the added benefits I mentioned previously), it makes more sense that they don't make such shape guarantees, imho -- vendors could still optimise for static shape, and fallback to non-optimised code if the instance's shape change, which I guess is what is done today with prototypes(?) and which I think should also be done for `with', but I digress. Still straying a bit from the main subject here, I thought type guards were supposed to be defined at the function level, no? Or is it that the shape of classes would be used to determine the types used? 2011/11/1 David Herman dher...@mozilla.com There may be something wrong with the above -- but dynamic super() should be a solveable problem for JS.next, even if not entirely desugar-able into ES3 terms. The problem isn't so much whether it's possible to come up with a semantics by changing the runtime; I'm sure we could do that. The problem is finding a way to get the semantics you want without taxing the performance all other function calls in the language. (Also known as a pay-as-you-go feature: if you don't use the feature, it shouldn't cost you anything.) We don't know how to do that for super(). So I guess in theory I agree it'd be nice if super() and class could be designed completely orthogonally, but in practice they affect each other. But at the same time, I think a class syntax where the body is restricted to be declarative is actually a nice sweet spot anyway. You can still dynamically create classes just like always, but the declarative form gives you a sweet and simple syntax for the most common case. Dave Yes, |super| is static to avoid the cost of passing an additional parameter to every function call, whether that uses |super| or not. Object.defineMethod is provided to make functions with bound |super| to other objects. I also think that dynamic |super| makes more sense with JavaScript, but vendors are concerned about performance -- plus, Object.defineMethod should cover the other cases, albeit not as nicely as dynamic |super| would. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Minimalist Classes
On 01/11/11 22:18, Brendan Eich wrote: On Oct 31, 2011, at 6:57 PM, Jeremy Ashkenas wrote: 'Evening, ES-Discuss. After poking a stick in the bees' nest this morning (apologies, Allen), and in the spirit of loyal opposition, it's only fair that I throw my hat in the ring. Here is a proposal for minimalist JavaScript classes that enable behavior that JavaScripters today desire (as evidenced by libraries and languages galore), without adding any new semantics beyond what already exists in ES3. https://gist.github.com/1329619 Let me know what you think, and feel free to fork. Thanks, I did fork, and I made a Rich Corinthian Leather version, for the reasons given in the comments. In brief, I contend that over-minimizing will please no one: class haters still gonna hate, while class lovers used to batteries-and-leather-included will find the bare sheet metal poky and painful. Love it or hate it, I'm ok either way :-P. But I do crave intelligent responses. /be I like how clean the syntax is there, Brendan. I still feel class syntax would have more value if they presented a nice way for object composition besides inheritance. None the less, I think we could well get rid of those `var' inside the class-body, as long as it's not executable: https://gist.github.com/1332633 ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Minimalist Classes
On 02/11/11 00:01, Brendan Eich wrote: On Nov 1, 2011, at 6:57 PM, Quildreen Motta wrote: I like how clean the syntax is there, Brendan. I still feel class syntax would have more value if they presented a nice way for object composition besides inheritance. Traits were factored out and I consider adding them in this exercise to be a bridge too far. Fair enough. None the less, I think we could well get rid of those `var' inside the class-body, as long as it's not executable: I don't think so, although Bob Nystrom's suggestions ended up simplified that way. It's awkward to use assignment expression as a declarative form. It suggests the body *is* executable. Instead, I went with 'var' as Bob did originally. My view is that 'var' will die hard and for global-object-aliasing global variables, it's close to class prototype properties. There's no way to observe the prototype half-initialized. As noted, there's a risk people will think methods close over proto-vars/consts. /be Hm, I don't think `lhs = rhs' suggests any more of a non-declarative form than `var'. Taking JS semantics into consideration, I'd say `var' is more misleading (whereas `lhs = rhs' just feels weird). There's `public', but then, that's quite verbose. I guess people comming from a classical language with declarative definitions for class slots might still be used to it, none the less. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: More thoughts on Allen’s class definition pattern
I still think | is more straight-forward to grasp to non-native speakers -- they're likely to have stumbled upon that on UML classes, methinks. Also, there's the problem of creating new reserved words in the languages, imho it makes a language feel heavier and clunkier. I think one of the greatest point of ECMAScript is that, despite the awful amount of reserved words, the language still manages to be simple and straight forward for people to grasp, except for a few semantic quirks here and there. I don't think that evolution and simplicity have to be mutually exclusive. Languages should strive to hide the perceived complexity from the end-user, while still managing to be expressive. If we decide on using a keyword for expressing |, this word should be as straight-forward and simple to grasp for both native english-speaking people and non-native english-speaking people, which I don't think any of the proposed words are =/ 2011/10/31 Axel Rauschmayer a...@rauschma.de I searched a bit and re-read Smalltalk, Self, Cecil, and Io docs to get a handle on what | does. It is not 'clone'. It's not 'copy' (Self) either, clearly. It ain't 'create' except in a vacuous sense that's also already taken by ES5 Object.create. It isn't subsuming in my view. refinedBy is closer but you'll get camelCaps keywords into JS over my dead body! I landed on 'beget' because 'create' is close but vague yet poisoned, and we need something pithy. Also, 'beget' does match the sire or hatch connotation of taking a parent (Self again) object and differentialy inheriting another object from it via proto-linking. Clone means make a twin and mutate. Copy is, well, just a copy -- arguably close to clone and one char shorter (so Self chose well). What we have with | is more like generate a child -- hence, 'beget'. Two more ideas: const Employee = Person to { ... } // or any other preposition (prepositions are like operators) const Employee = Person parents { ... } -- Dr. Axel Rauschmayer a...@rauschma.de home: rauschma.de twitter: twitter.com/rauschma blog: 2ality.com ___ 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: On class literals possibly not making it into ECMAScript.next
On 30/10/11 01:07, Axel Rauschmayer wrote: Now, for the past few months, I've been defining my objects like this: // where `clone' = Object.extend(Object.create(proto), props) var Thing = function(){ return ( { clone: _clone , toString: toString }) function clone(name){ return clone(Thing, { name: name }) } function toString() { return '[thing ' + this.name + ']' } }() var Specific = function(){ return clone(Thing, { clone: _clone , toString: toString }) function clone(name){ return clone(Specific, { name: name }) } function toString() { return '[specific ' + this.name + ']' } }() var foo = Thing.clone('foo') var bar = Specific.clone('bar') Where is _clone in the above code? You also could write the functions into the object literals then you wouldn’t need an IIFE. Ah, those `clone' functions should be `_clone'. The underscore is just to avoid conflicts with the outer `clone' function. Anyways, it is a matter of taste. I write function-heavy style, so I find it better to write something(other(x)) than this.something(this.other(x)). Defining the objects inside a closure allows me to define these little helper functions that would otherwise just clobber the prototype object if exposed — I usually expose them under a `internal' property though, so I can test them. There's also the thing about my liking to have a list of all public properties of the object readily accessible in the code. With object literals it gets a bit more difficult, as the list of properties are lost in the definitions of such properties. How about the following variation of your code? Would that still reflect your intentions or go against your taste? It’s very close to your next proposed solution. var Clonable = { clone: function() { var inst = Object.create(this); inst.init.apply(inst, arguments); }, extend: function(props) { return Object.extend(Object.create(this), props); }, } var Thing = Clonable.extend({ init: function (name) { this.name = name; }, toString: function () { return '[thing ' + this.name + ']'; }, }); var Specific = Thing.extend({ // reuse Thing.init() toString: function () { return '[specific ' + this.name + ']'; }, }); var foo = Thing.clone('foo') var bar = Specific.clone('bar') /// Using an extended version of object literals var Thing = { constructor(name){ this.name = name } ,toString(){ return '[thing ' + this.name + ']' } } var Specific = Thing| { constructor(name){ this.name = name } ,toString(){ return '[specific ' + this.name + ']' } } var foo = new Thing('foo') var bar = new Specific('foo') That’s approximately how Irakli’s Selfish or my Prototypes as Classes work (both are ES5 libraries). Yes, and to which I think class-syntax would be just a duplicated sugar — as long as you have the new | and .{ operators, that is. The one thing class-syntax would excel at, though, is the current semantics for super calls in ES.next. I find them particularly confusing, considering the relationship between functions and objects in JS. They make more sense with a static declarative syntax, but that might be just me. Super-calls are the one thing that would stay the same between all current proposals! Hm, wouldn't most features covered by the class-syntax be independent of syntax in the end? My point was that the nature of static |super| fits more naturally the static nature of the class-syntax than the dynamic nature of prototypes, even though object literals are declarative. People are likely to think about class-syntax in the same manner they reason about them in classical languages, I guess. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: On class literals possibly not making it into ECMAScript.next
On 30/10/11 09:45, Rick Waldron wrote: On Oct 30, 2011, at 5:58 AM, David Bruantbruan...@gmail.com wrote: Le 30/10/2011 02:35, Quildreen Motta a écrit : (...) Are we overthinking classes? Perhaps the reason for all this thinking about classes come from the role constructor functions take in the language? I'm a bit sceptical on constructors and constructor's own properties being that important, though. I agree. Has anyone used constructor properties for static properties? Just considering the DOM, constants are put on the prototype and everyone sounds happy with it so far. In jQuery, John/we put static methods and properties on the jQuery() function - this practice is used for anything that is not a selector match operation. This includes Ajax and Deferred (among others). Considering jQuery is used on26.6million websites, it's safe to bet that practice is in common use. Rick Ah, when I said `important' I didn't mean in the sense of how much people use it. I meant that the functionality can be achieved with or without constructors. The only thing that changes is the order of importance of things. With constructors, the major player are functions — which arguably makes the semantics of prototypes a bit weird: function Thing(parent, name) { // instance properties this.name = name this.childs = [] if (parent) parent.childs.push(this) } // constructor properties Thing.sort = function(thing){ thing.childs.sort(function(o1, o2){ return o1.name o2.name }) return thing } // shared instance properties Thing.prototype.sort = function(){ return Thing.sort(this) } var something = new Thing(null, 'something') something.sort() Thing.sort(something) With objects as the major players, you still get static properties, due to the nature of delegative behaviour sharing that [[Prototype]] has, it's just a little different: Thing = { // instance properties new: function(parent, name) { this.name = name this.childs = [] if (parent) parent.childs.push(this) }, // shared instance properties sort: function() { this.childs.sort(function(o1, o2){ return o1.name o2.name }) return this }, // constructor properties static: { sort: function(thing) { return Thing.sort.call(thing) } } } var something = Thing.new(null, 'something') something.sort() something.static.sort(something) Of course, people seem to be too used to the class-like way of doing things, that proposing such could be regarded as madness. Plus, getting rid of constructors is not reasonable at this point in time; as Brendan said, we're basically stuck with every semantic quirk the language has got so far. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: On class literals possibly not making it into ECMAScript.next
On 29/10/11 21:03, Axel Rauschmayer wrote: There are two things is JavaScript that are simple and elegant and universally liked: - Prototypes - Object literals How come we can’t transport that simplicity to classes? Once the objects have been created, we are happy with them, but how to best set them up is still controversial. I still maintain that JS doesn't *really* need a declarative syntax for defining relationships between objects — call it classes if you will. What I really find lacking in the language are primitives that allow me to work with objects, by composing them, querying them, filtering them, whatever-ing them. I think people already stressed enough the why of having a declarative syntax for all that (tooling, describing intent, simplicity, etc, etc). But there's also value in not having another full-blown and different syntax, imho, as we already have the triangle operator(?), the monocle-moustache operator(?) and object literals. Now, for the past few months, I've been defining my objects like this: // where `clone' = Object.extend(Object.create(proto), props) var Thing = function(){ return ( { clone: _clone , toString: toString }) function clone(name){ return clone(Thing, { name: name }) } function toString() { return '[thing ' + this.name + ']' } }() var Specific = function(){ return clone(Thing, { clone: _clone , toString: toString }) function clone(name){ return clone(Specific, { name: name }) } function toString() { return '[specific ' + this.name + ']' } }() var foo = Thing.clone('foo') var bar = Specific.clone('bar') /// Using an extended version of object literals var Thing = { constructor(name){ this.name = name } ,toString(){ return '[thing ' + this.name + ']' } } var Specific = Thing | { constructor(name){ this.name = name } ,toString(){ return '[specific ' + this.name + ']' } } var foo = new Thing('foo') var bar = new Specific('foo') // Clear advantages: // - Familiar syntax, whilst managing to be quite okay to work with // - Declarative, but not static // // Clear disadvantages: // - Using `new' in this fashion would require changing semantics for objects // - Kinda conflicts with constructor functions. I'd think that factories // living inside objects and always creating new instances would be // better, but I know old semantics won't be changed =/ /// Using class syntax class Thing { constructor(name){ this.name = name } toString(){ return '[thing ' + this.name + ']' } } class Specific extends Thing { constructor(name){ this.name = name } toString(){ return '[specific ' + this.name + ']' } } // Clear advantages: // - Cleaner // - Can be easily extended to support sugars for traits, privates, and what-nots // // Clear disadvantages: // - Unfamiliar syntax (for the language itself, not for other languages) // - Fixed syntax // - Some could argue the name is quite misleading given the semantics, but I digress. Now, I'm not sure class-syntax alone solve the main problems of working with objects and structuring programs in JavaScript — unless you always structure your programs using a huge inheritance tree, I favour object composition, so the class-syntax doesn't change much of what I find particularly counter-productive in the language. Other people's mileage may vary. Anyways, what I feel the language should provide for aiding in the structure programs is: - A way of sharing behaviour — semantically covered by prototypes, and the | operator is a nice interface for Object.create. - A way of composing behaviours — traits and mixins. The latter is already widely used, afaics. Also the .{ operator. - A set of primitives for working with objects as sets — join, difference and intersection operations, for example. With class-syntax you can provide a nice interface to all those, but I believe the extension proposals to the Object literal already covers such cases as well, such that you'd get duplicated syntatical sugar for the same thing. The major difference I see is that class-syntax, once defined, will be fixed. They might cover most cases now, but that might not necessarily hold true as the language and programmers evolve. Providing primitives — they're mostly independent from class-syntax anyways, which is cool — allows programmers to evolve the patterns on their own as well. The one thing class-syntax would excel at, though, is the current semantics for super calls in ES.next. I find them particularly confusing, considering the relationship between functions and objects in JS. They make more sense with a static declarative syntax, but that might be just me. None the less, I believe the entry-barrier to both the object literal syntax and class-syntax to be in the same level, only the class-syntax looks cleaner and more elegant. Are we overthinking classes? Perhaps the reason for all this thinking about classes come from the role constructor functions take in the language? I'm a bit sceptical on
Re: Inner functions and the value of this.
On 15/10/11 11:47, Jake Verbaten wrote: Im suggesting the rule is value of this binds at location of function instantation. I would expect an invocation of the function elsewhere to still have the this value of the other function (o1 not o2). As long as people understand and follow the rule set it shouldnt be too confusing. Basically a function declaration/expression is automatically soft bound to the outer this. I think soft-bound functions would make more sense than the current `thisObject' rules, but it's perhaps too late to change the semantics now. ES.next is an evolutionary step, not a revolutionary one. I get mixed feelings about this. On one hand, I'd really love to see the semantic quirks solved, on the other, I'm not sure legacy code should break with the new version — perhaps it should, but Brendan mentioned that browsers vendors won't be maintaining two different VMs, so there's that. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: JsDoc based type guards
2011/10/14 Peter Dekkers pe...@jbaron.com Some of the advantages I could see: 1. JsDoc becomes a standard part of Language. This has to be a good thing even without using it is as basis for stronger typing: a uniform way of documenting code. I fail to see why One True Way for everything would be a good thing. It's true that this aids community grow, but the JS dev community is already too heterogeneous for that to work. See the endless discussions about Yay! Semicolons vs Yay! ASI, braces, indentation style, documentation style, object definition style, etc, etc, etc. 2. No new language constructs are required. That doesn't really make it an advantage. Unless the thing happens to be a de-facto standard, which I'd argue it isn't. I think my major pet-peeve against using strict types for contracts is: 1.) JS is not a statically typed language, it's an overtly dynamic language with prototypical OO. Using it as the former -- contracts as a way of enforcing is-a relationships -- is just ditching the whole language already. For this to really work, we'd need ways to define abstract types, interfaces, etc, etc, etc. Otherwise it's just bothersome with no added benefits. 2.) What you proposed is better delegated to being supported by tooling alone, as Jake mentioned. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: JsDoc based type guards
2011/10/14 Brendan Eich bren...@mozilla.com On Oct 14, 2011, at 9:25 AM, Quildreen Motta wrote: I think my major pet-peeve against using strict types for contracts is: 1.) JS is not a statically typed language, it's an overtly dynamic language with prototypical OO. Using it as the former -- contracts Contracts are not necessarily static. In many languages they are dynamic. The disnetdev.com/contracts.coffee/ work is a case in point. That's true. We've discussed contracts.coffee in the guards thread before too -- whose syntax I'm particularly keen to, only not in JS. I wasn't saying that contracts must be about static typing though, but that I got the impression that his post was hinting at using a is-a relationship to define contracts for certain functions. Nevertheless, guards are a strawman because having a single, extensible syntax for contracts, runtime checks, etc., could be useful to enough of the diverse JS community that standardization is worth the costs. We need more experience with this proposal, so I encourage people to implement it with a transpiler and experiment. Yes, guards are an interesting addition to the language. Not only for type safety (would we also be able to get multiple dispatch on type pattern matching then?), but for documentation. I personally like the optional typing in Dart, even though I'm a static-typing-hater (and the devs have already said they won't support type inference directly in the language), they're valuable as code intention annotations. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: JsDoc based type guards
2011/10/14 Jake Verbaten rayn...@gmail.com On Fri, Oct 14, 2011 at 2:44 PM, Peter Dekkers pe...@jbaron.com wrote: I think the entire proposal based on auto generating gaurds from documentation is not that useful. It forces you into a type of documentation. I want to choose my documentation, I dont want these choices forced onto me. +1 This is what I was trying to get at :3 ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: JsDoc based type guards
2011/10/14 Peter Dekkers pe...@jbaron.com I checked the strawman and it looks nice. However the introduction of something like :: would surely not run on older VM's that don't understand that construct. Is that not a perceived problem more in general: adding a nice new language constructs that people won't use due to the fact that xx% of VM don't support it? Most ES.next proposals are already not compatible with ES5. Why? Because nice syntax *matters*. It's not just about the semantics, surely semantics are good and all, but considering the lack of flexibility on JS's language syntax for introducing such new functionality in a nice manner, proposing better and usable syntax becomes overtly important. After all, syntax is the primary interface for programmers to express their thoughts, thus, it deserves plenty of thought. For functionality that should be backwards compatible, the support should come through APIs, frameworks, libraries and tooling. All of which can be already achieved for contracts. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Re: Grawlix
2011/10/13 Russell Leggett russell.legg...@gmail.com On Thu, Oct 13, 2011 at 12:46 PM, Douglas Crockford doug...@crockford.com wrote: On 11:59 AM, Brendan Eich wrote: CoffeeScript users have to know JS semantics, even if they don't think of it that way. Syntax was the point, though, and productivity should be higher with CoffeeScript provided the user learns it, all else equal. Do we have any evidence of that? Is there real value in reforming the syntax, or is it an illusion? I don't like C's syntax. It tastes too much like Fortran. I find Coffeescript much more to my liking. But I have found the issue of syntax to be polarizing. Some of the web developers I've been talking to love Coffeescriptish lightness. But I am doubtful that that lightness results in better productivity. Typing is not where we spend the bulk of our time. I don't think less typing results in better typing. As you've said, typing is not the time killer. However, I think the argument could be made that if people enjoy what they're doing more, they will be more productive. This article http://positivesharing.com/2007/03/top-10-reasons-why-happiness-at-work-is-the-ultimate-productivity-booster/makes the claim and backs it up with some research. Is coffeescript vs. javascript big enough to be the difference between being happy or not? I think that depends on the person, but based on its popularity, I would say for some people it is. Having tried both, I'm more inclined to JavaScript. While CoffeeScript is certainly cleaner and usually more readable -- less noises, etc --, the parser ambiguities and quirky indentation rules are terrible enough for me not to use it. I find JavaScript's syntax already pretty light comparing with other C-family languages, mainly due to ASI. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Minimal type guards?
Contracts would be interesting, but perhaps too expensive? fib :: (Number) - Number function fib(n) { return n == 0? 0 : n == 1? 1 : fib(n - 1) + fib(n - 2) } or function fib(n Number) - Number { } Not particularly proposing any syntax though. Not particularly keen on using fixed types though -- as JS is not statically typed and types are not particularly well defined, definitely not something I'd check for is-a relationships --, I'd rather go with a predicate functions, but then that's even more expensive. 2011/10/13 Axel Rauschmayer a...@rauschma.de Similar to the minimal classes idea: Is there a sweet spot between nothing at all and full-blown type guards that would have a chance to make it into ES.next? The minimal useful feature set that I can think of: 1. instanceof checks: is an argument an instance of a given type? 2. property name checks: enforce property names and property values. Use case: options in a function/method invocation. Axel -- Dr. Axel Rauschmayer a...@rauschma.de twitter.com/rauschma home: rauschma.de blog: 2ality.com ___ 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: Re: Grawlix
This is the whole reason I love Scheme :3 2011/10/13 Claus Reinke claus.rei...@talk21.com But I am doubtful that that lightness results in better productivity. Typing is not where we spend the bulk of our time. Good language designs tend to have light syntax (but not all light syntax languages have good designs). The reasons have more to do with reading, and mostly with thinking about code, not just with writing. On one side, there is code comprehension: bulky but consistent syntax can win over light but inconsistent syntax, because the surprises and exceptions hamper understanding more than the extra characters. Many coders from bulky syntax languages are afraid of lightweight syntax, because it (a) seems to take away the guiding framework of syntax or (b) seems to require a lot of re-learning (eg, symbolic operators). One has to realize that consistency makes for a better guiding framework than excessive syntax, and that lack of exceptions means that there isn't actually more to learn, because everything works the same way. This step takes a bit of a leap of faith, but if the language design is truly simple/general/consistent, then those who have taken that leap are very unwilling to go back (I'm tempted to compare it to taking off the training wheels, but won't do so for fear of being misunderstood;-). Note the importance of consistency: if the language is just a collection of shortcuts, or if there are too many unexpected corners and exceptions instead of general rules, short syntax is not going to make life any easier. On the other side, there are our limited brains: the less we have to pay attention to LOTS OF SUPERFLUOUS SYNTAX, the more complex code we can consider at once, in terms of problem-relevant concepts we encode. Light syntax alone doesn't improve productivity, nor do saved keypresses, but a language design that gets out of the coders' way, lets them focus on their ideas, and lets them express and hold large blocks of those ideas -in code- in their minds at once, that does. It does so by throwing fewer obstacles in the way, and light syntax tends to be one of the aspects of that process. Claus http://clausreinke.github.com/ __**_ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/**listinfo/es-discusshttps://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Minimal type guards?
2011/10/13 Brendan Eich bren...@mozilla.com On Oct 13, 2011, at 3:29 PM, Kris Kowal wrote: Your proposal resembles Waldemar’s guards and trademarks. http://wiki.ecmascript.org/doku.php?id=strawman:trademarks http://wiki.ecmascript.org/doku.php?id=strawman:guards You might consider building on these to make a contracts proposal, separating the signatures from the declarations. You all have seen http://disnetdev.com/contracts.coffee/, I hope. I think it's pretty apparent from my first example :3 Alex’s question is whether some subset of these ideas is suitable for rapid consensus. I will refrain from speculating. We don't need to speculate. These failed to get rapid consensus in the May TC39 meeting, where they were presented. Lots of issues, see the notes. https://mail.mozilla.org/pipermail/es-discuss/2011-May/thread.html#14748 I shall take a look at the proposals and subsequent discussions. I am not familiar with either. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Class literals: things ES.next could borrow from Dart
We already get factory constructors by default -- by returning an object from the constructor function. 2011/10/10 Axel Rauschmayer a...@rauschma.de In many ways, Dart feels *less* versatile than ECMAScript.next. However, there are two ideas that would make a nice addition to class literals: - Named constructors: Without overloading, you need a way to distinguish constructors: new Point.zero() - Factory constructors: are a way to mark constructors so that no instance is produced automatically. Then you can return cached instances or instances of a subclasses. Details: http://www.dartlang.org/articles/idiomatic-dart/ -- Dr. Axel Rauschmayer a...@rauschma.de twitter.com/rauschma home: rauschma.de blog: 2ality.com ___ 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: Class literals: things ES.next could borrow from Dart
By specs, a new instance is created and passed as the `thisObject' for the constructor function anytime that function is called with the `new' operator. It could be optimised as long as that object is not used. --- function Point(x, y) { this.x = x this.y = y console.log(this) return { x: x, y: y } } new Point(1, 1) instanceof Point // = false --- This can't be optimised because the `this' object is used. A more real-world use case would be, however: --- function Point(x, y) { if (!(this instanceof Point)) return new Point(x, y) this.x = x this.y = y } Point(1, 2) instanceof Point // = true new Point(1, 2) instanceof Point // = true --- Not sure how engines optimise that particular case, I'm not much familiar with JIT techniques either :3 2011/10/10 Axel Rauschmayer a...@rauschma.de Right. Does that prevent an instance from being created? But it shouldn’t be hard to let a compiler perform that kind of optimization. On Oct 10, 2011, at 13:58 , Quildreen Motta wrote: We already get factory constructors by default -- by returning an object from the constructor function. 2011/10/10 Axel Rauschmayer a...@rauschma.de In many ways, Dart feels *less* versatile than ECMAScript.next. However, there are two ideas that would make a nice addition to class literals: - Named constructors: Without overloading, you need a way to distinguish constructors: new Point.zero() - Factory constructors: are a way to mark constructors so that no instance is produced automatically. Then you can return cached instances or instances of a subclasses. Details: http://www.dartlang.org/articles/idiomatic-dart/ -- Dr. Axel Rauschmayer a...@rauschma.de twitter.com/rauschma home: rauschma.de blog: 2ality.com ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss -- Dr. Axel Rauschmayer a...@rauschma.de twitter.com/rauschma home: rauschma.de blog: 2ality.com ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Object.extends (was Re: traits feedback)
2011/10/7 John-David Dalton john.david.dal...@gmail.com As for the functionality, it should just be an n-ary function which extends the first object with all the _own_ properties of the other n-1 objects. If keys clash give right precedence. I've used this flavor of extends too (minus the own properties part). I also think this is the way to go. Object.extend should copy only own properties, though. Other use cases can be dealt with by creating a small abstraction to copy properties recursively. Or by providing a native .deepExtend. I'd assume the majority of the use-cases wouldn't want to deal with copying all descriptors -- taking into account we're not copying just enumerables here, it could well be a problem -- since it'd bring in too much overhead in each call. whether key clashes favour left or right isnt important. whether the return value is undefined or the first object isnt important. Yap but chaining FTW. I think Object.extend should return the target object. It makes no sense to do otherwise -- considering the majority of JS native API either returns an useful value, and most of them are pure. By the way, what are your thoughts on pure vs destructive Object.extend? ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: es-discuss Digest, Vol 56, Issue 57
2011/10/7 John J Barton johnjbar...@johnjbarton.com On Fri, Oct 7, 2011 at 8:34 AM, Axel Rauschmayer a...@rauschma.de wrote: If you do something like var fuz = Object.extend(foo, {paper:'in', shoes:'my'}); Then fuz will get all properties of Object.prototype, again, as duplicates. In the above, you are clearly most interested in what you see in the literal and those are the own properties. I don't understand how you can get properties as duplicates in JS. I disagree, since in my example I specifically point out that fuz.bar() should work. You can't get duplicate properties, because keys are unique. However, you'll still get loads of clutter in the target object. Also, again, I'm not sure the majority of the use-cases would be concerned with copying the properties in the whole prototype chain -- that's expensive! -- and you could achieve the latter easily by recursively extending the object. And this kind of extend enables poor man’s cloning as follows: var orig = { foo: abc }; var clone = Object.extend(Object.create(Object.getPrototypeOf(orig)), orig); Sadly this code will fail since -- surprise! -- Object.create() does not take an object as the second argument. Object.create here is only taking a single parameter though. `orig' is being passed to Object.extend. The kind of problems that arise when you have overtly verbose qualified names that you can't even keep track of what's where. I would prefer the name Object.copyOwnPropertiesTo(source, target) or Object.copyOwnTo(source, target) to the name “extend” (which, to me, suggests inheritance). See previous point. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Object.extends (was Re: traits feedback)
2011/10/7 John J Barton johnjbar...@johnjbarton.com On Fri, Oct 7, 2011 at 9:16 AM, Quildreen Motta quildr...@gmail.comwrote: 2011/10/7 John J Barton johnjbar...@johnjbarton.com On Fri, Oct 7, 2011 at 8:34 AM, Axel Rauschmayer a...@rauschma.dewrote: If you do something like var fuz = Object.extend(foo, {paper:'in', shoes:'my'}); Then fuz will get all properties of Object.prototype, again, as duplicates. In the above, you are clearly most interested in what you see in the literal and those are the own properties. I don't understand how you can get properties as duplicates in JS. I disagree, since in my example I specifically point out that fuz.bar() should work. You can't get duplicate properties, because keys are unique. However, you'll still get loads of clutter in the target object. Also, again, I'm not sure the majority of the use-cases would be concerned with copying the properties in the whole prototype chain -- that's expensive! -- and you could achieve the latter easily by recursively extending the object. Again I'll ask you to consider that fuz.bar() should work. That is what extend means. How can we solve this? We don't need to flatten the prototype chain, we can extend it. Object.extend(a,b) can return an object whose own properties are the own properties of |b| on those of |a| and the prototype chain of |b| appended to the prototype chain of |a|, dropping duplicate prototypes. I believe that would be solved more effectively with traits (Self traits, I haven't had the time to read JS's proposal on that yet). ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: traits feedback
2011/10/6 John J Barton johnjbar...@johnjbarton.com On Wed, Oct 5, 2011 at 10:37 PM, Brendan Eich bren...@mozilla.com wrote: On Oct 5, 2011, at 9:02 PM, John J Barton wrote: PrototypeJS (and Firebug) pre-date Object.keys() and .hasOwnProperty(), hasOwnProperty was in ES3 in 1999. PrototypeJS is IIRC 2005-era. Firebug is post-y2k. so their implementation was just what could be done, not what was desired. Seems unhistorical :-|. Ok, so what is your theory then? This code was written by two of the premier JavaScript developers. If for..in was intended, then Object.extend should also use for...in. The experiment has been done, and for..in is the correct semantics. If for..in was not intended then what? If developers of this caliber aren't using the new results here, that's really discouraging. Actually there is a third possibility: it really does not matter. The differences are not significant. Actually, I am not sure that having `Object.extend' copy all the enumerable (or all own enumerable) properties by default is a good thing. First, because that copying would be most expensive, and I don't think most usecases would require the parent properties to be copied as well -- not to say it's easier to have conflicts, even if we're talking just about enumerable here, but then, not copying all the own properties, enumerable or not, makes even less sense, imho. Second point being is the expensiveness without bringing in a powerful construct. If you need to grab the properties from an object alongside with its parents, you'd rather use a prototype. And it would be easier in this case if JS supported multiple [[Prototype]]s, like Self does. Object.extend then could be regarded just as a means of copying parent-less objects -- semantic-wise. Third point being that for additional use-cases it's easier to create an abstraction layer that recursively copies the descriptors. About own/own+enumerable, one has to ask what people use these extensions for. Right now, I believe most people are just copying data from one place to another, such that it's okay to copy only enumerable properties. But now, let's take into account that ES5 introduced property descriptors and getters/setters. Also, let's assume people wanted to use these for copying behaviours as well -- ie.: using the objects passed to Object.extend as mixins. In this case, I believe it makes more sense to copy all own descriptors rather than just the enumerable properties, as some behaviours might depend on a property that is there, but was intentionally marked as non-enumerable to avoid problems -- hash implementations could use that. I frankly don't think that these new semantic should be fully backwards compatible with ES3-only code, for I believe ES.next will take a while to be adopted. However, I would like hearing about what people's thoughts are on enumerable+own vs all own property copying without regards to what has been done in pre-ES5 code. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Grawlix
On 06/10/11 19:56, John J Barton wrote: Recent syntax discussions head in a completely different direction, introducing a seemingly large number of new symbols resulting in code that isn't readable by current JS, Java, or C devs. Instead of JavaScript they will be attempting to read GrawlixScript. I'm skeptical that this direction will be welcomed by developers. There already is lots of complaints about syntax from developers, and they always spring up when someone brings ES.next topic on ##javascript's IRC channel, for example. Though I do believe there are two different groups in this case, those who want syntax either for static/contracts or conciseness, and those who don't want syntax because it makes the language needlessly complex --- neither opposing all syntax proposals or accepting all of them. My personal opinion is that syntax should be kept minimal, while maintaining expressivity. Usually, well designed APIs provide a more expressive interface because you can mix and match them, and they are usually far cheaper (in complexity) than their syntaxes counterpart. Surely, where APIs would otherwise add too much boilerplate, we need syntax. But I don't think that, in a highly dynamic language like JS, declarative/static syntax for every construct should be a major concern. But then, I'm no language designer, only a regular user. And perhaps I've been too much spoiled by Scheme. jjb On Thu, Oct 6, 2011 at 12:19 PM, Douglas Crockford doug...@crockford.com mailto:doug...@crockford.com wrote: On 11:59 AM, John J Barton wrote: GrawlixScript is the connection I guess. No, grawlix is a term of art that can be used to describe some the literal syntax proposals. ___ 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: On I got 99 problems and JavaScript syntax ain't one
On 05/10/11 22:05, Brendan Eich wrote: On Oct 4, 2011, at 7:19 AM, Juan Ignacio Dopazo wrote: Yes, tools should be better, but they need to start becoming better by themselves as previous discussions here have noted. However, there are problems in the language that need to be addressed by both syntax and APIs. We need: - A sane way of dealing with equality, identity and basically a lot of what's in http://wtfjs.com/ Some of that is due to implicit conversions, not any equality-ish operator. I really never understood people's complaints about equality comparisons in JavaScript. There are only two operators, with clear and well defined semantics/use-cases: `==' (Abstract equality) is used for comparing the value of two objects, without taking data-structure into account. `===' (Strict equality) is used for comparing the value of two objects, taking data-structure into account. Could someone enlighten me on what is not intuitive or sane about that? I mean, my starting point for comparing equality operator sanity is Common Lisp's with its 10+ equality predicates — some being implementation-dependant, so YMMV. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: On I got 99 problems and JavaScript syntax ain't one
On 05/10/11 23:06, Brendan Eich wrote: On Oct 5, 2011, at 7:01 PM, Quildreen Motta wrote: On 05/10/11 22:05, Brendan Eich wrote: On Oct 4, 2011, at 7:19 AM, Juan Ignacio Dopazo wrote: Yes, tools should be better, but they need to start becoming better by themselves as previous discussions here have noted. However, there are problems in the language that need to be addressed by both syntax and APIs. We need: - A sane way of dealing with equality, identity and basically a lot of what's in http://wtfjs.com/ Some of that is due to implicit conversions, not any equality-ish operator. I really never understood people's complaints about equality comparisons in JavaScript. There are only two operators, with clear and well defined semantics/use-cases: `==' (Abstract equality) is used for comparing the value of two objects, without taking data-structure into account. This operator is insane due to implicit conversions it does when operand types are not the same. In such cases it is not an equivalence relation. I would argue this is not entirely true. It would depend on what you consider equivalence. As I said, the way I see the abstract equality algorithm is that it compares values — by which I mean primitive values, — such that it can't really take into account the data structure of the operands. So, `1' equals `1' which equals `[1]' which equals `{toString:function() 1}' which might equal just about any other object which `toString' returns 1. In this case, the semantics are pretty sane (though some might argue about `[1]' and other objects). We could say it would be analogous to having a book in several different medias — ebook, paper, audio, etc. Just because the medias are different, it doesn't mean the contents of the book are. I have to agree, however, that some of the conversions are not as intuitive — at first glance — as the ones in the relational operators, which always convert the operands to the a numeric primitive value. Perhaps some of the fault of abstract equality's usage might be on the lack of chaining comparisons, though: --- // This is not what you'd usually assume it to be, based on mathematical notation 2 == 2 == [2] // = false // ...because operations are done this way (2 == 2) == [2] → (2 == ToNumber(2)) == [2] → (2 == 2) == [2] → true == [2] → true == ToPrimitive([2]) // [2].valueOf().toString() → ToNumber(true) == 2 → 1 == ToNumber(2) → 1 == 2 → false --- That said, I don't consider the semantics of abstract equality *that* complex to consider it a problem — there are some recursive conversions, yes. ToPrimitive might get confusing depending on how toString and valueOf are defined in the object. That might be a problem or an interesting feature depending on the particular use-case, considering how dynamic JS is. That's not to say it's perfect in every single conversion, but it gets at least 90% of all the practical use cases right. Other people probably have a different opinion on this kind of equivalence coming from a strong or static/strong typed background. `===' (Strict equality) is used for comparing the value of two objects, taking data-structure into account. This operator is fine, unless you want to test (NaN is NaN) or (-0 isnt 0). There, you need is/isnt. Is `egal' already in ES.next? ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: traits feedback
On 06/10/11 00:02, Juan Ignacio Dopazo wrote: On Wed, Oct 5, 2011 at 10:36 PM, Jake Verbaten rayn...@gmail.com mailto:rayn...@gmail.com wrote: Object.create does indeed require propertydescriptors as the second argument. This is the easiest way to send meta-data like read-only. However it's verbose and the defaults are restrictive. I've written a small library (github.com/Raynos/pd http://github.com/Raynos/pd) to make it less verbose, you might find it useful. That's what Object.getOwnPropertyDescriptors http://wiki.ecmascript.org/doku.php?id=strawman:extended_object_api would be for. I don't know why it hasn't gotten into Harmony yet. Hm, how exactly would `#getOwnPropertyDescriptors' fix the verbosity of property descriptors when creating new slots in an object? Or were you referring to another issue? If so, I missed it, would you care to explain a little better? ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Super-calls
On 03/10/11 19:49, Erik Arvidsson wrote: On Mon, Oct 3, 2011 at 14:50, Axel Rauschmayera...@rauschma.de wrote: It’s a performance thing support for dynamic super would slow everything down and is thus not worth it. In the current spec, there is a method for moving methods with super from one object to another. It’s not as elegant, but given the performance cost of dynamic super, it’s the right call. I'm not sure it is just a performance issue. I believe the semantics is wrong too. class B { a() { this.b(); } b() { print('B.b'); } } class C extends B { a() { super.a(); } b() { print('C.b'); } } var c = new C; c.a(); // Should print 'C.b' With a dynamic super the above would lookup b in the wrong object (B.prototype instead of C.prototype) As I understand, dynamic super is different from dynamic this. With dynamic super, you'd still get `C.b' in that call, because the `thisObject' from the a function remains the same, super only changes the object in which the method is looked upon. So, a desugared (and wrong, I reckon, but bear with me for awhile) way of writing that would be: var C = { a: function() { B.a.call(this) } b: function() { print('C.b') }} var c = Object.create(C) c.a() // 'C.b' The problem with that explicit `B' is that a function doesn't really belong to an object in JS, it might be assigned to anything, and it's expect that it'll work all the same. So, the engine would need a way of tracking what the next object in the prototype chain is for *looking up* the method to use. Once it finds that method, it applies the method to the current `thisObject'. The problem then, with dynamic super, becomes that one needs to pass the called method a hint of what the next object in the prototype chain is, since we can't use `this' — it'll always be the same in all methods called through `super'. Static super solves that problem by placing that information directly in the method, so it's just a lookup away. Dynamic super solves that problem by passing the information as an implicit parameter to *every* function call, just like `this', thus being a perf problem. I think it boils down to a performance vs semantics problem in the end. I personally think the semantics dynamic super provides fit better with a prototypical and overly dynamic language, as JavaScript is (at least ES5 is). ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Super-calls
On 03/10/11 20:44, Axel Rauschmayer wrote: super being rare and moving methods being rarer, I think the tradeoff for performance is OK, especially as there will be a method that allows you to move methods. If performance wasn’t an issue, dynamic super would be preferable. Hm, I wouldn't consider moving methods to be that rare, unless you're taking into account only people coding in a declarative style. In that case, moving a method would be a weird thing to do. On the other hand, if you're writing imperative prototypical code, moving methods might not be such a rare thing — more so if we take into account the lack of multiple-inheritance facilities in JS, which would lead someone to use things like mixins (thus, more overhead due to manual copying, but mixins are — or should be — parentless anyways). Note, though, that this is based only on my own code. I am not much knowledgeable about the general use-case of JavaScript, so feel free to correct me where I'm rambling non-senses :3 Another point is what here should refer to in a situation like: --- var oddball = { clone: function() { this.instances = (+this.instances || 0) + 1 return this } , describe: function() { return this.name + ' has ' + this.instances + ' copies' }} var object = oddball | { describe: function() { return '#object ' + super.describe() + '' }} var me = object.clone() me.name = 'Me' var another = { describe: function() { return 'The princess is in another castle.' }} me.describe() // = '#object Me has 1 copies' object.describe.call(Object.create(another)) // = '#object undefined has undefined copies' --- In this case, should `here' take into account the object in which the action `describe' is defined, in this case resolving to `oddball.describe', or should it take into account the object that was the target of the action, in this case resolving to `another.describe'. My opinion is that the latter makes more sense, but that's because I see `thisObject' not just as a data-container, but something that describes the full behaviours of a thing. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Another paren-free gotcha
2011/9/29 Peter van der Zee e...@qfox.nl On Thu, Sep 29, 2011 at 3:43 AM, Quildreen Motta quildr...@gmail.com wrote: I'm not sure how this is much different from the rules you have now with ASI, though if this were such a problem, a block statement could be required I'm trying to make sure we don't add another feature that we'll later describe as yeah, wish we could take that out, but we can't, that ship has sailed. This ship hasn't sailed yet and if it does, I'd like it to be as clean as possible. Yeah, perfecting things is something I can appreciate. My point, however, was that I couldn't see a problem with Waldemar's first example since they are consistent with the current ECMAScript semantics (ASI). I personally find languages with few divergent semantic constructs better because you have less to learn and worry about when coding. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: prototype focus
Ah, oh yes. I think I fail at mailing lists :3 2011/7/1 Peter Michaux petermich...@gmail.com Did you mean to send this to es-discuss? Peter On 2011-07-01, at 8:51 AM, Quildreen Motta quildr...@gmail.com wrote: Actually, in my opinion, constructor functions add needless complexity on JavaScript's inheritance mechanism, and yes, they do shift the focus from prototypical inheritance -- using constructors feels much more like creating a layer of metadata to extend some behaviours, than extending objects. With constructors, you basically have the following: 1.) Want to extend Foo (an object). 2.) Create a function Bar, write initialisation code (even if you don't need one). 3.) Set Bar.prototype to an object that clones Foo. 4.) use new Bar to construct a new object that extends Foo (and does initialisation) -- which might return some other object. 5.) Extend the new Bar object as you see fit. 6.) Use the object. With prototypes you have the following: 1.) Want to extend Foo (an object). 2.) Create a new object that points to Foo. 3.) Extend this new object -- which you can do either manually or by calling an initialisation function on the object. 4.) Use the object. The thing is: by removing the additional constructor function you simplify it. I had a really hard time trying to wrap my head around constructors and how they play with prototypes, lots of people out there face the very same problem when trying to use the OOP mechanisms that JavaScript provides, since it *looks* like the classical pattern they're used to, but in reality it works mostly different. You still see code around that does: function Foo() { } Foo.prototype = { describe: function(){ return 'Foo' } } function Bar() { } Bar.prototype = new Foo Some people are simply not aware that Foo is not a class, but something that is used to group initialisation and inheritance, so it would be only natural(?) for them to think that way when trying to extend something. Some people also think that `prototype' is a magical property used for inheritance of anything. With PaC you solve those problems by making the mechanisms that JS uses for inheritance explicit. That is, if you want to extend Foo, you just extend Foo. 2011/6/30 Peter Michaux petermich...@gmail.competermich...@gmail.com On Thu, Jun 30, 2011 at 4:46 PM, Axel Rauschmayer a...@rauschma.de a...@rauschma.de wrote: What problem have you solved by giving the prototype a name? The names I choose makes it clear to the reader that the prototype is one element (zero) in a set of elements (complex numbers). A name gives a reference to the object that is not related to any constructor function. Constructor functions are something separate from the prototype object (zero). The proposal is not (just) about giving prototypes names. Understood but it seemed that the proposal started from the idea that JavaScript needs to get back to its prototype roots. I don't think JavaScript has ever been far from its prototype roots especially if the programmer shifts to thinking about a prototype object instead of thinking about a functions prototype property. Problems that both prototypes-as-classes (PAC) and class literals (CL) are trying to solve are: - Subclassing is hard and not directly supported by the language: connecting prototypes, chaining constructors, super-references. Object.getPrototypeOf(this).foo.call(this) is pretty long. - Class properties are not inherited Class property inheritance is definitely a secondary issue compared with the instance objects themselves. (CoffeeScript copies them “manually”). Which I think is unsatisfactory and has a lot of gotchas when some properties are arrays and other properties have primitive values. -- It seems to me that perhaps the PaC drifted too far or perhaps started too far from what JavaScript has already. If the idea is to shift the focus more towards prototypes, then starting from something like what I've written and adding super syntax would be more consistent with what JavaScript already has. Peter If none of these issues are involved then today’s constructor functions are OK. Pros of each approach: (1) Pro CL: no need to support two kinds of classes: prototypes *and* constructor functions. (2) Pro PAC: look the same as class literals, but don’t need an extra translation step. (1) weighs heavily and will probably make it impossible to sell PAC to TC39. There is the precedent of Python having two styles of classes [1] at the same time, but I don’t think they diverged as heavily as constructor functions and PAC. If you want to argue against PAC benefits, take a look at Sect. 3 here: http://www.2ality.com/2011/06/prototypes-as-classes.html#3 http://www.2ality.com/2011/06/prototypes-as-classes.html#3 [1] http://stackoverflow.com/questions/54867/old-style-and-new-style-classes-in-python http