Sent from my Cricket smartphone es-discuss-requ...@mozilla.org wrote:
>Send es-discuss mailing list submissions to > es-discuss@mozilla.org > >To subscribe or unsubscribe via the World Wide Web, visit > https://mail.mozilla.org/listinfo/es-discuss >or, via email, send a message with subject or body 'help' to > es-discuss-requ...@mozilla.org > >You can reach the person managing the list at > es-discuss-ow...@mozilla.org > >When replying, please edit your Subject line so it is more specific >than "Re: Contents of es-discuss digest..." > >Today's Topics: > > 1. Re: Generator issue: exceptions while initializing arguments > (Dmitry Soshnikov) > 2. Re: Generator issue: exceptions while initializing arguments > (Kevin Smith) > 3. Re: Generator issue: exceptions while initializing arguments > (Jason Orendorff) > 4. Re: Generator issue: exceptions while initializing arguments > (Kevin Smith) > 5. Re: Some questions about Private Name Objects (Kevin Smith) > >On Wed, Sep 12, 2012 at 5:13 AM, Brendan Eich <bren...@mozilla.com> wrote: > > >> You say it's too error prone but you don't adduce any evidence. >> >> Meanwhile we have lots of extant code that does things like >> >> function foo(bar, baz) { >> baz = baz || default_baz; >> ... >> } >> >> That's the cowpath we are paving. >> > >I see. Although, I cannot recall any other language which uses complex >expressions (such as function calls, or even referencing to the neighbor >parameters) for defaults. Usually they are just literals (no matter which, >primitive or objects -- they are recreated every time at activation). > >But, I agree, they way you describe brings more power, and maybe JS will be >the first language with such semantics for defaults. > >If so, then it's just the matter of the specification to notice all the >subtle cases. > >function getDefaul() {} > >function foo(bar = [], baz = bar, quz = getDefault()) { > function getDefault() {} >} > >The first thing which will confuse the devs is that `getDefault()` >expression is not the immediate function call to only _initialize_ the >default value of "quz", but is the syntactic form of calling this function >every time to calculate the default value. This should be mentioned very >explicitly, because from the top-down code viewing it really looks like >getDefault() is just an initialize of the default, and in this view, its >scope is even looks like the outer scope. > >Second, of course the scope of all the defaults expressions, with the bold >font: "Notice, that the scope of defaults evaluation is the body of the >function. This is done to support referencing to the neighbor arguments". > >As for generators, > >function createGen(foo = thrower()) { > yield 1; >} > >var gen = createGen(); // loc1 >gen.next(); // loc2 > >Of course the devs (again, w/o referencing to spec or detailed docs), would >expect that the "thrower()" is called right away when the "createGen" >function is defined. After they have read the docs, and now know that such >function calls are executed at function activation instead, they would >expect that the "thrower()" is called at "loc1", when the function is >activated to create the generator object. > >OTOH, we understand the technical implementation, that the call to >"createGen" may not execute the function body, and therefore, not to call >"thrower()". And this is again will be too confusing for novices (?) that >it (by the technical details/implementation?) should/may be an "loc2". > >So, if all these things described above are worth >doing/supporting/explaining/etc., then we can build defaults based on "foo >= foo || bar()" pattern which is used today. Then it's completely OK, I >agree, it's powerful. > >However, if to take new programmers which will join JS from now, >potentially they should not know about old patterns for defaults as "foo = >foo || default", and they can use simple defaults as literals only. > >In some/many languages the defaults are used with `null`s only to be able >to call a function with lesser parameters number. E.g. (PHP): > >function foo($foo, $bar = null) { > if (!$bar) { > $bar = $this->getDefault(); > } >} > >And now they can use foo(10), or foo(10, "bar"); But still, the expression >which calculates the default $bar is described explicitly inside (in the >scope of) the function. > >JS has no such problems, we may call foo(), or foo(10), or foo(10, "bar") >regardless default values, even today. > >Also, the fact, that the expressions should be calculated at activation, >not creation, comes from legacy, when function declarations should be >created on entering the context. Then, even this code: > >var foo = function () {}; > >function bar(baz = foo()) { > ... >} > >Should not logically work, since "bar", being a FD, is created on entering >the context, when "foo" is not function yet. This can satisfy the >activation frame + activation time rules for such expressions. > >Dmitry > >> >> We still have the choice of the implicit yield going after argument >> defaulting, not before. SpiderMonkey implements before, though, and my own >> argument from compositionality, above, makes it more clear to me that we >> should go with implicit-yield-first. This makes contrived throwing >> parameter default expressions throw "late" but if that matters, use a >> function combined with a generator. >> >> In this thread, you and I have agreed on simpler scope/hoisting/defaulting/ >> **initialisting a la ES1-5. I think on reflection that this argues for >> the implicit yield in a generator function going before anything with >> observable effects, including argument defaulting. > > >Sorry to backtrack the thread, but this is going to cause riots. > > function* g(a, b = makeTheWorldABetterPlace()) { ... } > > let iter = g(123); > // Is the world a better place yet? I hope so. > iter.next(); > >No amount of argument is going to convince a user that defaults should >*not* be executed at the location of the call. That's just not how it >reads. No? > >Kevin > >On Thu, Sep 13, 2012 at 8:23 PM, Kevin Smith <khs4...@gmail.com> wrote: >> No amount of argument is going to convince a user that defaults should *not* >> be executed at the location of the call. That's just not how it reads. No? > >I kind of agree, but at this point we could do with a little less >argument and a little more in the way of concrete proposals. > >So here is a concrete proposal. Please improve on it; it’s an honest >attempt, not a straw man in the rhetorical sense... > >I think Allen is proposing a scheme where in code like > > function f(a1=EXPR1, a2=EXPR2, a3=EXPR3) { ... } > f(); > >first EXPR1 is evaluated in a scope including only a1, >then EXPR2 is evaluated in a scope that contains a1 and a2, >then EXPR3 is evaluated in a scope that contains a1, a2, and a3, >then a new environment is created for the function body, its vars and >local functions. > >If EXPR1 contains a closure that uses the name a2, that means the >global a2, not the argument a2. Even if it gets called after a2 is >bound. > >In the spec language this would have to be modeled with four nested >environments; a single mutable environment wouldn't work. In >SpiderMonkey, if any of the EXPRs contained a closure that uses with >or direct eval, we would have to actually reify one of the nested >environments. Ugly but doable; any other implementors want to comment? > >There would have to be some specification hackery to make this work >just like ES3 in cases where f also contains a var or function with >the same name as an argument. But Allen can do it. :) > >I don’t have a strong preference. It seems to be is a classic Right >Thing vs. Worse Is Better situation. The advantage of the Worse Is >Better approach is that you can correctly and completely explain >what’s going on in one sentence: “It’s just like an if statement at >the top of the function body.” It may not be reasonable, but ordinary >developers can reason about it. When it comes to corner cases, which >is more important? > >-j > > >> >> I don’t have a strong preference. It seems to be is a classic Right >> Thing vs. Worse Is Better situation. The advantage of the Worse Is >> Better approach is that you can correctly and completely explain >> what’s going on in one sentence: “It’s just like an if statement at >> the top of the function body.” It may not be reasonable, but ordinary >> developers can reason about it. When it comes to corner cases, which >> is more important? >> > >Apologies for not making this clear earlier, but I agree with the "Worse is >Better" approach. That is, execute defaults in the scope of the function >body. When I tried to formulate the scope boundaries (as you have) it >became clear to me that it would be convoluted any other way. > >What I'm questioning now is the idea that, in generators, the implicit >first yield should occur *before the defaults are evaluated*. I don't >think that's a tenable position. Is there an implementation problem with >inserting the implicit first yield *after* the defaults are evaluated but >*before* the rest of the function body? > >Thanks for your time on this, BTW. > >Kevin > >> >> The real point I'm trying to make is that Name objects give us something >> akin to clojure's protocols. Imagine an "orm" protocol -- this is just a >> set of names that must exist on an object (or its proto chain). An object >> can implement any number of protocols (or interfaces, or whatever) without >> fear of conflict. You can easily override any implementation so long as you >> have a handle on the appropriate name object. This is easier, better >> looking and more correct than anything we can do today. It's not too >> disimilar from using using instanceof as a brand, but without the pitfalls >> (it doesn't fall flat crossing sandbox boundaries). This is a safe and >> flexible inheritance model that works just as a js programmer would expect, >> all without begging for mutable or multiple prototypes. >> > >I think this is a winning argument. So the problem becomes: how can we >implement this in a non-fugly way? As it stands (and as Allen has pointed >out), we don't currently have the syntax to make this work, even for >"iterator": > > import iterator from "sys:iterator"; // Sorry, hate @'s : ) > > class Derived extends Base { > > // Hmmm... No way to put iterator here. > } > > // Try here? Fugly... > X.prototype[iterator] = function() { > > super.doSomething(); // Oops - super outside of class definition : ( > }; > >The absolute minimum we need is a way to specify computed property names in >classes (and what the heck, object literals too): > > import iterator from "sys:iterator"; > > class Derived extends Base { > > [iterator]() { > super.doSomething(); // Works like a charm! > } > } > >This is IMO the best way forward. It's generally useful beyond the use >case presented here and does not use up a valuable free ASCII character. > It also doesn't require any new symbolism since we already understand that >brackets indicate computed property names. Why were computed property >names killed again? > >Kevin > >_______________________________________________ >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