Re: Operating with arbitrary timezones
On Sat, Aug 6, 2016 at 4:27 AM, Alexander Joneswrote: > I'm not sure I properly conveyed myself above given what you're saying. > Let me back up and explain more clearly now I have an actual keyboard in > front of me. > > Currently we have `Date.prototype.toLocaleString()`, which conflates two > concerns: > > 1. Taking an unambiguous *time point* to a { year, month, day, hours, > minutes, seconds, milliseconds, timezoneOffset } for the selected > *timezone* (which is the subject of this thread). > 2. Formatting those "local datetime components" in a way appropriate to a > specific locale. > > Ah -- you're right. I didn't understand what you were getting at before. This was very helpful. Thanks. - J ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Operating with arbitrary timezones
On Fri, Aug 5, 2016 at 6:32 PM, Jon Zeppieri <zeppi...@gmail.com> wrote: > > > On Fri, Aug 5, 2016 at 6:21 PM, Alexander Jones <a...@weej.com> wrote: > >> Don't confuse timezones with timezone offsets. They are different >> concepts. > > > > How am I confusing them? You wrote: > > What I meant by Date+Time components was actually { year, month, day, >> hours, minutes, seconds, offset }. I think it makes sense to formalise this >> as an expression of a time point (aka Date) *in a particular timezone*. For >> example this can be used to decide e.g. "are these two time points in the >> same month in this specific timezone", where that month may be e.g. 31 days >> + 1 hour. It could also be formatted for display. > > > And I'm saying, in response, that if you want to formalize the concept of > a time point in a particular time zone, this isn't a good way to do it. If > instead you want to formalize the concept of a particular point in time at > a particular UTC offset, then it's fine, of course, but at that point, I'd > just reiterate Tab's response. > > - Jon > Actually, let me try to clarify this a bit more. It sounds like you do not want a DateTime type to contain (what I would call) a robust concept of a time zone, because you think that date "projections" (by which I think you're referring to the kind of date arithmetic that I mentioned in an earlier post) are a separate concern. (I'm fine with that, by the way. Off the top of my head, I can't think of any date/time libraries that use a time zone as a separate input to date arithmetic functions, but it's a reasonable design.) However, you say that it would be useful to have the offset as part of a DateTime object, so that you could answer questions like: "Are these two points in time in the same month in this specific time zone?" Well, first question: which specific time zone (offset, actually, since that's what you want in the objects, right)? We're talking about either a two argument predicate function or a binary method, I assume. You might say that it doesn't matter which offset you use -- coerce in either direction you want; they're either in the same month or not. True (under certain assumptions, which I'll get back to in a moment) -- but if you're not interested in which month (and which offset), then you don't need the offset in the representation at all, because if you could coerce both to UTC to answer the question, then... well, you could just represent them in UTC. And all of this assumes that the question is a meaningful one to start with. I'll happily elide the question of what calendar we're talking about, but assuming we only care about the proleptic Gregorian calendar: when would you ever be interested in whether two points in time fall within the same month at a given UTC offset -- as opposed to a more robust notion of time zone? I might, at some point, care if two points in time are in the same month in America/New_York, but I can't imagine why I'd ever care if they are thus in UTC-5:00 -- precisely because UTC-5:00 doesn't really designate an area that uses the calendar in such-and-such a way, while America/New_York does. I suppose this is my long-winded way of saying that the very projections that you'd (understandably) like to avoid are implicit in almost any time zone-related question you'd want to ask. - Jon ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Operating with arbitrary timezones
On Fri, Aug 5, 2016 at 6:21 PM, Alexander Joneswrote: > Don't confuse timezones with timezone offsets. They are different concepts. How am I confusing them? You wrote: What I meant by Date+Time components was actually { year, month, day, > hours, minutes, seconds, offset }. I think it makes sense to formalise this > as an expression of a time point (aka Date) *in a particular timezone*. For > example this can be used to decide e.g. "are these two time points in the > same month in this specific timezone", where that month may be e.g. 31 days > + 1 hour. It could also be formatted for display. And I'm saying, in response, that if you want to formalize the concept of a time point in a particular time zone, this isn't a good way to do it. If instead you want to formalize the concept of a particular point in time at a particular UTC offset, then it's fine, of course, but at that point, I'd just reiterate Tab's response. - Jon ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Operating with arbitrary timezones
On Fri, Aug 5, 2016 at 5:58 PM, Alexander Joneswrote: > What I meant by Date+Time components was actually { year, month, day, > hours, minutes, seconds, offset }. I think it makes sense to formalise this > as an expression of a time point (aka Date) *in a particular timezone*. For > example this can be used to decide e.g. "are these two time points in the > same month in this specific timezone", where that month may be e.g. 31 days > + 1 hour. It could also be formatted for display. > > Conflating Date projections into a timezone, with formatting, is a bit of > a conceptual error IMO. Convenient, but incorrect, as per Single > Responsibility Principle. > > Alex > > UTC offsets are terrible representations of time zones, because they don't acknowledge that many actual local timelines are discontinuous. When you don't need time zones, it's best to avoid them (and UTC offsets) altogether, but when you really need them, UTC offsets just aren't enough. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Operating with arbitrary timezones
On Fri, Aug 5, 2016 at 5:30 PM, Tab Atkins Jr.wrote: > On Fri, Aug 5, 2016 at 1:59 PM, Kris Siegel wrote: > >> Once you endow them with a timezone offset they cease to represent > points > >> in time, but rather more points in space, which adds complexity and > >> liability to any code handling Date objects > > > > > > I would disagree. Time isn't useful without a point in space (space and > time > > should be looked at as one thing, not two) and since the Date object > tracks > > it internally as UTC it has a default space. > > This is incorrect. It tracks a UTC timestamp; the current time as I > write this is 1470432591121 milliseconds since the epoch, and that's > true regardless of where you are on the planet. > Yep. > > Timezones are a *display* concept - they affect how you parse > human-readable strings into timestamps, and how you display a > timestamp as a human-readable string. This is similar to the > distinction between Unicode values and strings encoded in UTF8. > Time zones are not *just* for display. They're are also necessary for doing date arithmetic on a local timeline (assuming the most common and, IMO, useful sort of date arithmetic). For example: if I ask you, "What date and time is it exactly one day after March 12, 2016 at 3pm in the America/New_York time zone," how do you answer? If you take "one day" to mean 24 hours, then the answer is March 13, 2016 at 4pm in America/New_York (because of daylight saving time), but most libraries that implement date arithmetic will give you March 13, 2016 at 3pm, etc., etc. -- because that's what users tend to expect out of date arithmetic (as opposed to time arithmetic). - Jon ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: January 19 meeting notes
On Fri, Jan 20, 2012 at 7:25 AM, Grant Husbands esdisc...@grant.x43.net wrote: Jon Zeppieri wrote: Is there a version of this desugaring that deals with recursive bindings in the initializer expression of the loop? How about something like this? (given for (let varName = initExpr; testExpr; updateExpr) { body } ) { let varName = initExpr; while(true) { if (!testExpr) { break breakTarget; } let tempVar = varName; { // There might be a better way to copy values to/from shadowed variables // (using temporaries seems a bit weak) let varName = tempVar; continueTarget: { body } tempVar = varName; } varName = tempVar; updateExpr; } } That way, all of the variable references in initExpr, testExpr and updateExpr refer to a singular copy and all of the variable references in body refer to the iteration-scoped ones. It doesn't satisfy Desirable Property #3 from the previously cited email: 3) The rewrite rules are the *same,* regardless of whether it's a for (var ...) or a for (let ...) loop. But that's the least important property. So, looking at your example: for (let [i, inc] = [0, function() {i++;}]; i n; inc()) ... I think it now has the desired behaviour. However, people calling inc from inside the body will still be surprised. Yeah, that's a problem. I think solving that probably requires something more advanced than a desugaring, as it means the loop variables captured by that function (or, alternatively, ones captured inside the body) need to point at different variables at different times. That's my suspicion, as well, and I'm curious whether this affects TC39 members' opinion. It's not entirely clear from Brendan's email what caused him, Waldemar, and David Herman to hop off the fence in support of the fresh-binding-per-iteration approach, but it sounds to me like they were initially concerned about needing to specify a complicated semantics and were persuaded by MarkM's argument that the problem could be solved syntactically. There's also an abstraction leakage if one breaks in the body, in that the inner varName doesn't get copied to the outer one. All in all, not a great desugaring, but I thought it might be worth offering. Maybe disallowing capture in the for (let ...;...;...) head would be easier. I still think there's something misleading about taking a loop with an imperative update and re-binding behind the scenes, despite the fact that the problem it's trying to solve is definitely a real problem (I've been bitten by it myself). It's one thing if the difference really isn't observable except in the case where a closure captures the iteration variable (as Sam suggests), since it's hard to imagine anyone wanting the current binding behavior in that case. But the recursive binding cases make me a bit uneasy. -Jon Regards, Grant Husbands. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: January 19 meeting notes
On Fri, Jan 20, 2012 at 5:08 PM, Jon Zeppieri zeppi...@gmail.com wrote: It's one thing if the difference really isn't observable except in the case where a closure captures the iteration variable (as Sam suggests), since it's hard to imagine anyone wanting the current binding behavior in that case. But the recursive binding cases make me a bit uneasy. Heh. Of course, the recursive binding cases *are* cases where a closure captures the iteration variable... The distinction I was trying to draw is between the normal case, where the binding is captured in the body, and the oddball cases I've mentioned, where it's captured in the loop initializer. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: January 19 meeting notes
On Thu, Jan 19, 2012 at 11:02 PM, Brendan Eich bren...@mozilla.org wrote: Yes kids, this means we are going with MarkM's lambda desugaring from: https://mail.mozilla.org/pipermail/es-discuss/2008-October/007819.html Is there a version of this desugaring that deals with recursive bindings in the initializer expression of the loop? In my post (https://mail.mozilla.org/pipermail/es-discuss/2008-October/007826.html), I used an example like: for (let fn = function() { ... fn(); ...};;) There are other, related cases, like: for (let [i, inc] = [0, function() {i++;}]; i n; inc()) ... In that earlier post, I wrote that the modifications [to MarkM's desugaring] needed to make these work are pretty straightforward, though I can't recall what I had in mind at the time. Waldemar's option (above) solves the recursive function case, but not the local-inc case. Even as the loop rebinds i and inc, the latter will continue to refer to (and increment) the initial binding of i. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Block lambda is cool, its syntax isn't
On Thu, Jan 12, 2012 at 4:26 PM, Thaddee Tyl thaddee@gmail.com wrote: I have heard many fellow programmers say that, while block lambdas would be welcome, Ruby's |a, b| syntax is ugly. I thought I was the only one feeling this way, but since I am not, I would like to ask why the parentheses cannot be used there. { (a, b) a + b } cannot conflict with any existing program; at least I don't see how it can. And if people choose to use newlines in their code? {(a, b) a + b} ... already has a meaning. -Jon ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Block lambda is cool, its syntax isn't
On Thu, Jan 12, 2012 at 5:52 PM, Allen Wirfs-Brock al...@wirfs-brock.com wrote: On Jan 12, 2012, at 2:23 PM, François REMY wrote: Am I wrong if I say there not a bigger issue with block lambda than with the current object notation on the matter? I think you're correct. An ExpressionStatment can not begin with a { so,without changing that rule, there should be no potential for ambiguity between Block and BlockLambda. The only issue is distinguishing ObjectLiteral and BlockLambda and from that perspective a {( is as good as a {| as neither is ambiguous with existing ObjectLiteral syntax, An additional consideration: for a block lambda's completion value to be another block lambda, the {( syntax would require parenthesis, while the {| syntax would not: let succ = {(x) {(s) {(z) s(x(s)(z)) }}}; With the grammar François is suggesting, this would be a syntax error (I think), since the body of a block lambda is a StatementList_opt. The {| syntax, on the other hand, can accommodate block lambdas as expression statements, though, given another token of lookahead (again, I think). ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Block lambda is cool, its syntax isn't
On Thu, Jan 12, 2012 at 7:11 PM, Allen Wirfs-Brock al...@wirfs-brock.com wrote: On Jan 12, 2012, at 3:41 PM, Jon Zeppieri wrote: ... With the grammar François is suggesting, this would be a syntax error (I think), since the body of a block lambda is a StatementList_opt. The {| syntax, on the other hand, can accommodate block lambdas as expression statements, though, given another token of lookahead (again, I think). With two token look-ahead a | BlockLambda could be allowed at the head of a statement, but it still would not enable unparenthesized object literals at the head of a statement. It seems like a cognitive burden to allow one but not the other. A simple { at the start of an expression statement must be parenthesized rules seems easiest to learn and remember. Allen That's a good point, but I think that unparenthesized block lambdas might be worth this complication. I hadn't considered object literals, at all, while writing the previous message, and I don't think that was simply an oversight. Object literals and blocks have a similar syntax but dissimilar meaning. Block lambdas, on the other hand, are semantically kinda-sorta like blocks. You don't need to parenthesize nested blocks in JS code. (In fact, you can't.) That leads me to expect unparenthesized block lambdas. I guess it depends, to some extent, whether you think block lambdas and object literals have more in common with each other (both being first-class values) than block lambdas and blocks do (both being lists of statements). ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Tennent's correspondence principle and loop-local variable capture
On Thu, Jun 30, 2011 at 7:27 PM, Mark S. Miller erig...@google.com wrote: On Thu, Jun 30, 2011 at 4:07 PM, Brendan Eich bren...@mozilla.com wrote: The old C-style for(;;) loop is a hard case. It really does want a single shared-mutable loop control variable. Making 'let' instead of var in for (let i = 0; i N; i++) ... bind afresh on each iteration and communicate the ++ update across the loop edge is theoretically doable, but it's wrong. Why is it wrong? I showed a de-sugaring of for(;;) into lambda that creates a separate binding per iteration. (I can try to find it in the es-discuss archive if it would be helpful.) Because when I write i++ I expect mutation. -Jon ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: block lambda revival
On Wed, May 25, 2011 at 11:06 AM, Brendan Eich bren...@mozilla.com wrote: One last thought: if you want to curry, always parenthesize all calls. Space-separated argument lists just do not look sufficiently high precedence when followed by (...) after, to treat foo {|x| x} (bar) as foo({|x| x})(bar) instead of foo({|x| x}, bar) /be Agreed. My comment was off-base. I don't expect currying here. I'm more worried about the foo({|x| x}(bar)) interpretation. That is to say, the different meanings of (bar) in {|x| x}(bar) and foo {|x| x}(bar) make me wince a bit. -Jon ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: block lambda revival
On Wed, May 25, 2011 at 4:01 PM, Brendan Eich bren...@mozilla.com wrote: On May 25, 2011, at 8:44 AM, Jon Zeppieri wrote: {|x| x}(bar) The new grammar forbids that, though. You must parenthesize the block-lambda to invoke it with a parenthesized argument list: ({|x| x})(bar) Block-lambdas are most commonly used as actual arguments, not as literal callees in call expressions. To avoid trouble of the kind Waldemar pointed out, they must be caged by parentheses on the outside to be used that way. Ok, I don't see a place for BlockLambda outside of call contexts in your grammar, so I didn't get that. Or is your addition to PrimaryExpression ( CallWithBlockArguments ) suposed to be ( BlockLambda ) ? And examples like let empty = {| |}; are now let empty = ({| |}); -Jon ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: block lambda revival
On Fri, May 20, 2011 at 8:54 PM, Brendan Eich bren...@mozilla.com wrote: As promised/threatened: http://wiki.ecmascript.org/doku.php?id=strawman:block_lambda_revival Sorry to take a step back here. After reading Waldemar's comments, I took a closer look at the formal grammar, and I'm puzzled by the production rule you've added to CallExpression: CallExpression [no LineTerminator here] BlockArguments Should that be: MemberExpression [no LineTerminator here] BlockArguments instead? This may just be the sleepiness talking, but it looks like a CallExpression always starts with MemberExpression Arguments which would require a parenthesized argument list. -Jon ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: block lambda revival
On Tue, May 24, 2011 at 3:29 PM, Brendan Eich bren...@mozilla.com wrote: BlockArguments : BlockLambda BlockArguments [no LineTerminator here] BlockLambda BlockArguments [no LineTerminator here] ( Expression ) The interleaved parenthesized expression worries me for two reasons: - Waldemar's currying hazard doesn't strike me so much as a hazard as it does expected behavior. But that might just be me. - If the the parenthesized expression is a comma expression, e.g., f{|x| x}(a, b, c) I might expect a, b, and c to be spliced into the arguments list, whereas, given the formal grammar, I assume a and b will be evaluated for side-effects, and c will be the argument. -Jon ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: block lambda revival
On Sat, May 21, 2011 at 10:43 AM, Brendan Eich bren...@mozilla.com wrote: On May 20, 2011, at 9:55 PM, Peter Michaux wrote: On Fri, May 20, 2011 at 5:54 PM, Brendan Eich bren...@mozilla.com wrote: An essential part of this proposal is a paren-free call syntax Why is that essential? The argument, as I understand it from Smalltalk, Ruby, and E experts, is empirical, and in part a matter of intentional design: users write blocks as actual parameters to make control abstractions. Most such abstractions taking block arguments do not let those blocks escape through the heap or a return value -- the blocks are downward funargs. This aids in making new control abstractions more efficient than functions to implement, as well as more usable. Built-in control flow statements have (optionally) braced bodies that do not need parenthesization, so why should new ones created by users passing blocks? I like the proposal. I'm not sure I follow the above, though. I get the point about un-parenthesized blocks making for better control abstraction syntax; I'm just not clear on how that relates to the downward funargs point. In Ruby, for example, the anonymity of the implicit block argument prevents its capture and guarantees that the param is downwards-only. It seems unrelated to parenthesis. Since the strawman only addresses the call syntax, I figure that it doesn't affect formal argument syntax -- I mean, that you're not proposing something like Ruby's implicit, anonymous, last formal. Since block args would be named, and since they are first-class (evidenced by the examples in the strawman), I'm guessing that they are allowed to escape up the stack. But I may have missed something basic. -Jon ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: block lambda revival
On Sat, May 21, 2011 at 8:54 PM, Brendan Eich bren...@mozilla.com wrote: On May 21, 2011, at 4:23 PM, Jon Zeppieri wrote: I'm just not clear on how that relates to the downward funargs point. It doesn't. Two separate points. Sorry, I should have used a bulleted list or something :-P. Thanks for the clarification. In Ruby, for example, the anonymity of the implicit block argument prevents its capture and guarantees that the param is downwards-only. It seems unrelated to parenthesis. Right, and we are convinced that this is an unnecessary concession in Ruby's design toward ease of implementation. Analyzing Harmony code to link uses to definitions it not hard, and arguments.callee is poisoned pill (already; ES5 strict). Absolutely agree. -Jon ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Spread and non objects
On Fri, Nov 5, 2010 at 8:14 AM, P T Withington p...@pobox.com wrote: [2p. from the Lisp world, the putative inventor of the rest/spread operator.] In Lisp, arglists are lists instead of arrays, the operator is `.`, and conveniently, the empty list, `()`, and Lisp null, `NIL`, are just two ways to write the same atom. In Lisp, option B just falls out: (f . NIL) === (f . ()) === (f) +1 for B as the best approximation (in the absence of a List data type). If the closest analogue of a Lispy list is an ESy array, then I think the empty array would be the best approximation. We can't really have the symmetry that Zeppieri is looking for because you want the rest operator to return an empty array when there are no rest args (rather than null), so you don't need to test for null before manipulating a rest arg. I can (finally) articulate my initial intuition (in favor of Erik's plan A). To the extent that the spread operator and rest args should be symmetrical, the following function should be an identity over its domain: function id(x) { return (function(...x) { return x; })(...x); } But it can only be an identity when its argument is an array. Whether or not anyone else cares about this symmetry is another matter. Second issue: Erik suggests (plan B) that null and undefined are specifically special cased. I can't tell whether Brendan agrees with that or wants spread to be legal on any input whatsoever, because he writes that spread should return an empty array on mismatch. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Spread and non objects
On Fri, Nov 5, 2010 at 11:16 AM, Mike Samuel mikesam...@gmail.com wrote: 2010/11/5 Jon Zeppieri j...@bu.edu: To the extent that the spread operator and rest args should be symmetrical, the following function should be an identity over its domain: function id(x) { return (function(...x) { return x; })(...x); } But it can only be an identity when its argument is an array. What do you think should happen with id(arguments)? I tend to think it's best to launder arguments where possible to stop the spread of unintended authority early. No argument here. My claim about id only being an identity when its argument is an array assumes that the rest arg mechanism works as proposed -- i.e., that the rest parameter is always bound to an array, not to an array-like or anything else. So, if symmetry were valuable, then id(arguments) would throw. But... I hadn't realized that the spread proposal already included array-likes. In that case, there is no symmetry to preserve. The (now badly misnamed) id function will produce an array from an array-like -- and from null or undefined, under plan B. I think that second part feels a bit hack-y, and as Brendan pointed out, spread isn't simply sugar for apply. Plan B is meant to eliminate an inconvenient null check, but I'm a bit concerned that the proposed behavior will simply hide actual bugs, as automatic coercions often do. That said, automatic coercions are commonplace in ES already. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Spread and non objects
On Thu, Nov 4, 2010 at 9:12 PM, Brendan Eich bren...@mozilla.com wrote: On Nov 4, 2010, at 6:07 PM, John Lenz wrote: It would seem friendlier for the spread operator to treat it them as a empty array otherwise you end up with code like: if (x!=null) { f(1,2,...x) } else { f(1,2) } Yeah, null testing is a drag. People skipt it (I hear this about regexp exec -- it should return an empty array on mismatch -- counter-argument is that empty arrays are truthy). The dual of spread-as-operator is spread-as-rest-arg-syntax. What happens in the case of: function foo(x, y, ...z) { [...] } foo(1, 2, null); Will z be bound to an empty array or to an array containing a single null? I'd expect the latter, and that answer seems more in-line with Erik's plan A. -Jon +1 on Erik's plan B. /be On Thu, Nov 4, 2010 at 5:54 PM, Erik Arvidsson erik.arvids...@gmail.comwrote: We've run into an edge case with the spread operator. What should happen if we try to spread null or undefined? f(...undefined); A. Throw an error B. Follow the path of Function.prototype.apply and others and special case null and undefined and just call f with 0 arguments -- erik ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Spread and non objects
On Thu, Nov 4, 2010 at 10:06 PM, Jon Zeppieri j...@bu.edu wrote: On Thu, Nov 4, 2010 at 9:12 PM, Brendan Eich bren...@mozilla.com wrote: On Nov 4, 2010, at 6:07 PM, John Lenz wrote: It would seem friendlier for the spread operator to treat it them as a empty array otherwise you end up with code like: if (x!=null) { f(1,2,...x) } else { f(1,2) } Yeah, null testing is a drag. People skipt it (I hear this about regexp exec -- it should return an empty array on mismatch -- counter-argument is that empty arrays are truthy). The dual of spread-as-operator is spread-as-rest-arg-syntax. What happens in the case of: function foo(x, y, ...z) { [...] } foo(1, 2, null); Will z be bound to an empty array or to an array containing a single null? I'd expect the latter, and that answer seems more in-line with Erik's plan A. Erm, on second thought, I got that completely wrong. The fact that z would be [null] doesn't pose any problem for plan B. The rest arg syntax always ensures that z is bound to an array, so it makes good sense that the operator would always produce one. -Jon +1 on Erik's plan B. /be On Thu, Nov 4, 2010 at 5:54 PM, Erik Arvidsson erik.arvids...@gmail.comwrote: We've run into an edge case with the spread operator. What should happen if we try to spread null or undefined? f(...undefined); A. Throw an error B. Follow the path of Function.prototype.apply and others and special case null and undefined and just call f with 0 arguments -- erik ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Spread and non objects
On Thu, Nov 4, 2010 at 10:34 PM, Jon Zeppieri j...@bu.edu wrote: On Thu, Nov 4, 2010 at 10:06 PM, Jon Zeppieri j...@bu.edu wrote: On Thu, Nov 4, 2010 at 9:12 PM, Brendan Eich bren...@mozilla.com wrote: On Nov 4, 2010, at 6:07 PM, John Lenz wrote: It would seem friendlier for the spread operator to treat it them as a empty array otherwise you end up with code like: if (x!=null) { f(1,2,...x) } else { f(1,2) } Yeah, null testing is a drag. People skipt it (I hear this about regexp exec -- it should return an empty array on mismatch -- counter-argument is that empty arrays are truthy). The dual of spread-as-operator is spread-as-rest-arg-syntax. What happens in the case of: function foo(x, y, ...z) { [...] } foo(1, 2, null); Will z be bound to an empty array or to an array containing a single null? I'd expect the latter, and that answer seems more in-line with Erik's plan A. Erm, on second thought, I got that completely wrong. The fact that z would be [null] doesn't pose any problem for plan B. The rest arg syntax always ensures that z is bound to an array, so it makes good sense that the operator would always produce one. Oh my. Take three. Spread-as-rest-arg-syntax constructs an array. Spread-as-operator splices the elements of an array into an argument list. So, if a spread operator expression: ...null splices zero values into an argument list, then its counterpart would be something like: function foo(x, y, ...z) { } foo(1, 2); ... where we pass zero optional arguments to foo, and z is bound to an empty array. Which is what we'd expect. So, yeah, plan B makes sense. -Jon +1 on Erik's plan B. /be On Thu, Nov 4, 2010 at 5:54 PM, Erik Arvidsson erik.arvids...@gmail.com wrote: We've run into an edge case with the spread operator. What should happen if we try to spread null or undefined? f(...undefined); A. Throw an error B. Follow the path of Function.prototype.apply and others and special case null and undefined and just call f with 0 arguments -- erik ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Spread and non objects
On Thu, Nov 4, 2010 at 10:48 PM, Jon Zeppieri j...@bu.edu wrote: Spread-as-rest-arg-syntax constructs an array. Spread-as-operator splices the elements of an array into an argument list. So, if a spread operator expression: ...null splices zero values into an argument list, then its counterpart would be something like: function foo(x, y, ...z) { } foo(1, 2); ... where we pass zero optional arguments to foo, and z is bound to an empty array. Which is what we'd expect. So, yeah, plan B makes sense. Ugh. Sorry for working out my confusion in posts to this list. Of course, the example above isn't a satisfactory counterpart to the ...null expression, since it doesn't anywhere involve a null. I suppose there is no real counterpart in the rest arg syntax. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Concise functions, Nonexistent lambdas, Explicit tail calls
On Tue, Dec 9, 2008 at 5:42 PM, Michael Day [EMAIL PROTECTED] wrote: Hi Jon, This will break existing code: http://www.google.com/codesearch?q=lang%3Ajavascript+%22var+fun%22hl=enbtnG=Search+Code As will lambda: http://www.google.com/codesearch?hl=enlr=q=lang%3Ajavascript+%22var+lambda%22sbtn=Search Or practically any other keyword we can think of. So this problem exists for many of the proposed syntactic extensions to JavaScript. Is there any way other than opt-in to introduce to new keywords without breaking existing code? Aside from picking really odd keywords? I don't think so. That's why people have been discussing the use of non-identifier ASCII punctuation. The benefit seems vanishingly small. I don't think it's enough to cover the (admittedly minor) cost in language complexity. Mozilla already has expression comprehensions, albeit without the parentheses, so this aspect can be evaluated now. JS also has a more powerful expression language than ES, so it wouldn't be an entirely accurate evaluation. It could be that Harmony will adopt many of the JS additions, though. Refraining from adding a new lambda construct will make JavaScript easier to specify... If you're right about this, I'd consider it a powerful argument against the lambda proposal. It's not obvious, however. Everything currently in the specification describing functions will still need to be there, even if some of it is rewritten to be expressed in terms of lambdas. On top of that, lambdas will need to be described. This will make the spec longer, and have more constructs that need to be understood. Harmony almost certainly won't use the pseudocode specification style of current ES specs. So, I have no idea how long the spec will be. I do know, however, that having more things to describe does not necessarily entail a longer text, and I also know that length and complexity don't have as simple a relation to one another as you seem to imply. And I'm not convinced that describing functions in terms of lambdas makes them easier for implementors to understand than just describing their behaviour directly. What does it mean to describe their behavior directly? The current ES specifications use a certain style of pseudo-assembly, along with a host of fictional entities, attributes, c. That is to say, they use a certain ad-hoc language that may or may not reflect the structure of an actual implementation. How is a description in this language any more direct than a description in an extended lambda calculus? They're both specification languages, only the latter is far better understood. -Jon ___ Es-discuss mailing list Es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Allen's lambda syntax proposal
On Sat, Dec 6, 2008 at 11:49 AM, Maciej Stachowiak [EMAIL PROTECTED] wrote: On Dec 5, 2008, at 11:12 PM, Jon Zeppieri wrote: I don't get it. What issue is raised by return-to-label that isn't already raised by exceptions? They're practically the same thing, only return-to-label is *easier* to analyze statically, because 'return' can only jump to a label that is lexically (not just dynamically) in scope. If you want to call a function and make sure control flow does not escape, then in the face of exceptions alone you can wrap it in try/catch. However, with multi-level returning lambdas, if you are passed a function then you have no way to prevent it from returning early, since it could be a lambda in the lexical scope of your caller. The strawman contains the following text: Unwinding the execution context may pass through finally blocks, which execute and may perform their own control effects, effectively canceling the unwinding. So, you have a dynamic-wind-like mechanism, if you need it. Also, what was the performance issue? -Jon ___ Es-discuss mailing list Es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Allen's lambda syntax proposal
On Sat, Dec 6, 2008 at 2:03 PM, Maciej Stachowiak [EMAIL PROTECTED] wrote: On Dec 6, 2008, at 9:57 AM, Jon Zeppieri wrote: On Sat, Dec 6, 2008 at 11:49 AM, Maciej Stachowiak [EMAIL PROTECTED] wrote: On Dec 5, 2008, at 11:12 PM, Jon Zeppieri wrote: I don't get it. What issue is raised by return-to-label that isn't already raised by exceptions? They're practically the same thing, only return-to-label is *easier* to analyze statically, because 'return' can only jump to a label that is lexically (not just dynamically) in scope. If you want to call a function and make sure control flow does not escape, then in the face of exceptions alone you can wrap it in try/catch. However, with multi-level returning lambdas, if you are passed a function then you have no way to prevent it from returning early, since it could be a lambda in the lexical scope of your caller. The strawman contains the following text: Unwinding the execution context may pass through finally blocks, which execute and may perform their own control effects, effectively canceling the unwinding. So, you have a dynamic-wind-like mechanism, if you need it. I guess then the damage can be contained, but it's unusual to use a mechanism like this for normal control flow rather than just exceptional conditions. I'd say that under the proposed semantics, return from lambda isn't normal control flow; it's a (potentially) non-local jump. Normal return inside a lambda is just falling off the end. Also, what was the performance issue? It turns return inside a lambda into a construct that has to unwind the stack (and apparently run finally handlers), which makes its cost more like the cost of throwing an exception than the cost of a normal return. Yes, because it is very similar to throwing an exception. Would you prefer that return inside lambda instead return from the lambda's own activation? That could be done, with some violence to TCP. In the most common case, however -- namely, return from function, which, under Dave's proposal, desugars to a return from lambda -- couldn't the additional cost be optimized away easily? You can determine statically that the jump doesn't unwind the stack, so the cost of returning should remain the same. In most implementations, throwing an exception is much more expensive. Actually, it could be worse than throwing an exception, since if you can't actually unwind the call stack until you find whether the lambda's containing function is currently on the stack. Okay, but you only incur this expense when you actually take the non-local exit. There is no reason why normal returns should be more expensive. -Jon ___ Es-discuss mailing list Es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Semantics and abstract syntax of lambdas
On Fri, Dec 5, 2008 at 9:20 PM, David-Sarah Hopwood [EMAIL PROTECTED] wrote: Semantic or abstract-syntax issues that are not settled include: - how to avoid the hazard pointed out by Mark Miller where a value can be unintentionally leaked from the tail position of a lambda; Can we take a step back? Before determining how to avoid the hazard, perhaps we should discuss whether it's worth avoiding. First, a question for the people who see a hazard here: is the hazard somehow peculiar to the ES lambda proposal? Because from Mark's description, he would have equal justification for citing a hazard in the design of Scheme, Lisp, c. Since I've never heard a schemer complain about this before, I'm more than a little skeptical of the danger. Here is Brendan's example: lambda (secret) { compute(secret); void 0; } Brendan notes that too few will remember to [add the void statement], so implicit return values will tend to leak. Should I read this as too few ES programmers, who aren't used to expression languages, will forget... c.? If so, then why does anyone suspect that people unfamiliar and uncomfortable with expression languages will abandon functions for lambdas? If not, should I draw the conclusion that expression languages are intrinsically broken? (I'm not buying that.) - whether the primitive form of a lambda has a block, statement, or expression as its body; The only problem with the proto-proposal to limit lambda bodies to expressions (which is otherwise a good idea) is that the ES expression sub-language isn't powerful enough. The ternary expression is awful for conditionals more complex than if a then b else c. Without a let expression, people would be nesting immediately applied lambdas, which quickly becomes unwieldy. Without a letrec expression, they would be forced into vomit-inducing syntactic horrors to bind local recursive functions. So, unless people want to expand the expression grammar significantly, I think the expression body is a nonstarter. A statement body (as opposed to a block body, I mean) just seems bizarre. Does it have some advantage? For now, I think Dave's proposal wins. -Jon ___ Es-discuss mailing list Es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Allen's lambda syntax proposal
On Thu, Dec 4, 2008 at 3:23 PM, David-Sarah Hopwood [EMAIL PROTECTED] wrote: Jon Zeppieri wrote: And, if it is on the same line, it's still bad for a top-down parser: ^(x) { x = x * x ^(a,b,c,d,e,f,g) {x} } Same result as above. Actually, I think we're both wrong. If I'm reading the spec correctly, no semicolon would be inserted, and the whole thing would be a syntax error. The offending token here is '{', but it's not separated from the previous token -- namely, ')' -- by at least one LineTerminator. At any rate, it's a problem. -Jon ___ Es-discuss mailing list Es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Allen's lambda syntax proposal
[oops, sent from the wrong address...] 2008/12/4 Breton Slivka [EMAIL PROTECTED]: this may be a stupid question, but why? Is it really so impossible to have λ(a,b,c){} ? Last time I brought this up, Brendan made fun of me on a podcast. :( You guys seem to have no trouble typing it. It's not that much trouble to remap a key, and you can always keep lambda(a,b,c){} as a more verbose but more accessable alternative. IDEs could make a macro out of it so you wouldn't even have to bother with going to the trouble of remapping. Exactly what I wrote then. I admit this seems ludicrous at its face, but admittedly I have not really seen the arguments against λ as an abbreviated lambda syntax yet. Well aside from the random guy doesn't know how to map a key problem (which is perfectly true), I could see some character set issues in the field. On Thu, Dec 4, 2008 at 5:35 PM, Brendan Eich [EMAIL PROTECTED] wrote: On Dec 4, 2008, at 2:31 PM, Breton Slivka wrote: I admit this seems ludicrous at its face, but admittedly I have not really seen the arguments against λ as an abbreviated lambda syntax yet. Not compatibly: ES3 already allows Unicode identifiers, including Greek Lambda. Also including the word 'lambda' -- but that hasn't stopped it from being seriously considered. -Jon ___ Es-discuss mailing list Es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Allen's lambda syntax proposal
On Thu, Dec 4, 2008 at 6:10 PM, Brendan Eich [EMAIL PROTECTED] wrote: On Dec 4, 2008, at 2:45 PM, Jon Zeppieri wrote: 2008/12/4 Breton Slivka [EMAIL PROTECTED]: this may be a stupid question, but why? Is it really so impossible to have λ(a,b,c){} ? Last time I brought this up, Brendan made fun of me on a podcast. :( Not you personally! I hope that was at least a :-/ emoticon... Oops. You see the typographical limitations we're still saddled with? The mock-wounded :( and the actually-wounded :( aren't slated to have distinct code points until Unicode 17. If we have to go to one character, though, I'd rather we use an ASCII punctuation character, for the reasons given (hard to type, slight incompatibility). But you λ fans need to help me here: how does one type λ on a Mac laptop? How about on a standard Windows machine? Pick a Linux and lay the clues on there, too. I'm a lot more likely to do this within emacs (or an editor, in general) than at the system / window system level. Anyhow, ASCII punctuation is great, if we can settle on a candidate. -Jon ___ Es-discuss mailing list Es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Allen's lambda syntax proposal
2008/12/2 Brendan Eich [EMAIL PROTECTED]: I think the only candidates have to be of the form ^(a, b, c) {...} (^ could be another character, but it seems to beat \ as others have noted), Was there a problem with \ other than the fact that it can't easily be turned into a binding form, à la \userFn() {...} ... due to the \u ambiguity? Because the Smalltalk-like syntax doesn't have an obvious binding form either. { userFn |a, b, c| ... } is potentially already valid ES3, depending on the contents of '...' . -Jon ___ Es-discuss mailing list Es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Allen's lambda syntax proposal
2008/12/3 P T Withington [EMAIL PROTECTED]: - prefix ^ might be confused with the infix operator of the same name With semicolon insertion, isn't this a bigger problem? The opening brace will need to be on the same line as the formals, otherwise the syntax is ambiguous: ^(x) { x = x * x ^(a,b,c,d,e,f,g) { x } } And, if it is on the same line, it's still bad for a top-down parser: ^(x) { x = x * x ^(a,b,c,d,e,f,g) {x} } Will semicolon insertion be illegal inside a lambda body? -Jon ___ Es-discuss mailing list Es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Allen's lambda syntax proposal
On Wed, Dec 3, 2008 at 9:36 PM, Eric Suen [EMAIL PROTECTED] wrote: No, ^(x) is not a legal expression, so you don't have to make block in same line, no semicolon insertion will happens here. You're looking at the wrong part of the example. Sorry -- the wrapper lambda is superfluous, and I should have left it out for clarity. Using the GNU bracing style: x = x * x ^(a,b,c,d,e,f,g) { x } The above parses as an xor expression followed by a block, like so: x = x * x ^ (a,b,c,d,e,f,g) { x } ... which is odd, to be sure, but perfectly legal. The second example: x = x * x ^(a,b,c,d,e,f,g) {x} is not ambiguous, but it's unsuitable for top-down parsing. (I tried to underscore the point by using a long list of formals.) The parser has to get to the opening brace before it can determine that it isn't dealing with an xor expression. -Jon see this post: https://mail.mozilla.org/pipermail/es-discuss/2008-December/008296.html - Original Message - From: Jon Zeppieri [EMAIL PROTECTED] Newsgroups: gmane.comp.lang.javascript.ecmascript4.general To: P T Withington [EMAIL PROTECTED] Cc: es-discuss [EMAIL PROTECTED] Sent: Thursday, December 04, 2008 3:09 AM Subject: Re: Allen's lambda syntax proposal 2008/12/3 P T Withington [EMAIL PROTECTED]: - prefix ^ might be confused with the infix operator of the same name With semicolon insertion, isn't this a bigger problem? The opening brace will need to be on the same line as the formals, otherwise the syntax is ambiguous: ^(x) { x = x * x ^(a,b,c,d,e,f,g) { x } } And, if it is on the same line, it's still bad for a top-down parser: ^(x) { x = x * x ^(a,b,c,d,e,f,g) {x} } Will semicolon insertion be illegal inside a lambda body? -Jon ___ Es-discuss mailing list Es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Allen's lambda syntax proposal
On Wed, Dec 3, 2008 at 9:52 PM, Eric Suen [EMAIL PROTECTED] wrote: Because it is a xor expression, for lambda, it will be x = x * x ^ ^ (a,b,c,d,e,f,g) { x } I don't understand what you're getting at. That's a syntax error. My example: x = x * x ^(a,b,c,d,e,f,g) { x } is not a syntax error, but it also (unfortunately) doesn't contain a lambda expression. Or am I missing something? -Jon ___ Es-discuss mailing list Es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Allen's lambda syntax proposal
On Wed, Dec 3, 2008 at 10:16 PM, Eric Suen [EMAIL PROTECTED] wrote: Yes, it doesn't contain a lambda expression, just like: a = x /x/i is not same as: a = x; /x/i they both right but has different meaning... Okay -- so we agree. In that case, it's clear that your proposed syntax: (a,b,c) {...} has the same problem, right? Any valid ES3 infix operator will have the same problem, if we use it as a prefix lambda operator. ___ Es-discuss mailing list Es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: How much sugar do classes need?
On Tue, Dec 2, 2008 at 1:54 PM, Peter Michaux [EMAIL PROTECTED] wrote: On Mon, Dec 1, 2008 at 12:01 PM, David-Sarah Hopwood [EMAIL PROTECTED] wrote: var self = { method toString: {|| '' + self.getX() + ',' + self.getY() + ''}, method getX: {|| x}, method getY: {|| y}, field pubInstVar: 4, const pubInstConst: -4, }; return self; where the extensions to the object literal syntax used here are: - a 'field' modifier to declare a property non-[[Configurable]], - a 'const' modifier to declare a property non-[[Configurable]] and non-[[Writable]], - a 'method' modifier to declare a property non-[[Configurable]], non-[[Writable]] and non-[[Enumerable]]. I don't think only a method would have the combination of attributes listed above. Agreed. The proposed names do not denote what they appear to denote. Also because functions are first class in JavaScript, I think of a function valued property as a field so don't like the name field. Also would method be able to be a lambda or function? From David-Sarah's description, it seemed to me that 'method' merely means that the property is non-configurable, non-writable, and non-enumerable and has nothing to do with the 'type' (as it were) of its value. And that's a good example of how the proposed names are misleading. There are 2^3 = 8 combinations of Configurable, Writable, Enumerable and potentially more attributes in the future. I'd prefer to control them independently. If multiple prefix modifiers are not appealing, what about some flags like the 'g' that can follow a regexp literal (e.g. /a/g) var self = { toString[]: {|| '' + self.getX() + ',' + self.getY() + ''}, getX[]: {|| x}, getY[]: {|| y}, pubInstVar[WE]: 4, pubInstConst[E]: -4, }; I find this ugly, but I don't have any great ideas. I do want to point out, however, that one important combination is omitted in David-Sarah's proposal (modifier names aside). Private instance variables would likely be represented as non-configurable, non-enumerable, yet writable properties. I'm guessing that 'x' and 'y' (which are suggested by, but left out of the examples above) would fit that description. -Jon If no brackets are included then it would be equivalent to [WEC] as that is backwards compatible (I think). I'm not sure I like this idea. It is just an idea. Peter ___ 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 much sugar do classes need?
On Tue, Dec 2, 2008 at 2:35 PM, Jon Zeppieri [EMAIL PROTECTED] wrote: ... I do want to point out, however, that one important combination is omitted in David-Sarah's proposal (modifier names aside). Private instance variables would likely be represented as non-configurable, non-enumerable, yet writable properties. I'm guessing that 'x' and 'y' (which are suggested by, but left out of the examples above) would fit that description. OK -- I just revisited the older messages in the thread. 'x' and 'y' are lexically bound (by the constructor function). So, ignore the above... ___ Es-discuss mailing list Es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: How much sugar do classes need?
On Tue, Dec 2, 2008 at 1:54 PM, Peter Michaux [EMAIL PROTECTED] wrote: var self = { toString[]: {|| '' + self.getX() + ',' + self.getY() + ''}, getX[]: {|| x}, getY[]: {|| y}, pubInstVar[WE]: 4, pubInstConst[E]: -4, }; If no brackets are included then it would be equivalent to [WEC] as that is backwards compatible (I think). I'm not sure I like this idea. It is just an idea. Another just an idea: #{ ... } is an object initializer where all of the initialized properties are non-configurable. 'enum' (or something similar) is a property modifier that makes the property enumerable. 'const' continues to have the same meaning (non-configurable and non-enumerable). Where 'const' appears inside #{ ... }, the non-configurable aspect is redundant. var self = #{ const toString: {|| '' + self.getX() + ',' + self.getY() + ''}, const getX: {|| x}, const getY: {|| y}, enum pubInstVar: 4, enum const pubInstConst: -4 }; It's more verbose than Peter's syntax, but it doesn't overload the array index syntax, and although the #{ ... } initializer unfortunately introduces new syntax, I think its functionality is genuinely (and generally) useful. I'd imagine that most real-world uses of { ... } could be replaced by #{ ... }, since initialized properties are usually expected to stick around. On the other hand: enum const get foo () { ... } ... is odd. -Jon ___ Es-discuss mailing list Es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: How much sugar do classes need?
On Tue, Dec 2, 2008 at 4:58 PM, Peter Michaux [EMAIL PROTECTED] wrote: I think if there are to be modifiers than just have the modifiers and not the #{}. Having all the modifiers with the property seems like a better way to go to me. That seems fine to me, too. The #{ ... } idea just struck me, because I realized that it pretty well captures what I actually *mean* when I use { ... }. Also what if #{} is used to create the object and later a property is added and is to be configurable? Is that possible? Either decision seems arbitrary. Yes, and I don't consider that arbitrary, at all. The meaning of obj.foo = bar; can't be dependent upon the mechanism used to create obj. Now, if #{ ... } were to seal the object, then obviously you couldn't add a new property to it. While sealed (and frozen, for that matter) initializers would be useful in places, just enforcing non-configurability of the initial set of properties seems like a reasonable trade-off between general usefulness (like I said, I bet that most uses of { ... } could be replaced by #{ ... } without a problem) and optimizer-friendliness. (I'm thinking of Mark's number (6) from earlier in this thread.) Of course, there could also be initializers for sealed and frozen objects. E.g., #s{ ... } and #f{ ... } -- or whatever. And these would be more optimizer-friendly and less generally useful than #{ ... }. And each would introduce new syntax. I'm in the minimize new syntax camp. If there are going to be modifiers config, enum, and const then there may be no harm in having other modifiers which represent a combination of these modifiers (like the suggestions of field and method though I don't really like those names for the reasons I wrote before.) Well, I think it's just a good practice to keep the set of modifiers (and new syntax, in general) small. -Jon ___ Es-discuss mailing list Es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: For Loop Desugaring (was: return when desugaring to closures)
On Mon, Oct 13, 2008 at 10:48 PM, Mark S. Miller [EMAIL PROTECTED] wrote: On Mon, Oct 13, 2008 at 5:00 PM, Jon Zeppieri [EMAIL PROTECTED] wrote: I'm talking about a rewrite from 'for' to 'lambda' that satisfies the following properties: 1) for (var i = 0; i len; i++) ... continues to mean what it means in ES3. 2) for (let i = 0; i len; i++) ... has the proper scope for 'i' (which you reiterated above), *and* 'i' is rebound -- not mutated -- on each iteration. 3) The rewrite rules are the *same,* regardless of whether it's a for (var ...) or a for (let ...) loop. At least, that's what I took Mark to mean. He can correct me if I'm wrong. You're right. However, the desugaring is more complex than I expected. Thanks for asking me to write it down. for (keyword varName = initExpr; testExpr; updateExpr) { body } desugars to (hygienic renaming aside): breakTarget: { const loop = lambda(iter = initExpr) { keyword varName = iter; if (! testExpr) { break breakTarget; } continueTarget: { body } lambda(iter2 = varName) { keyword varName = iter2; updateExpr; loop(varName); }(); }; loop(); } I believe this meets all your requirements. I believe it does. Very cool. It won't handle the fully general for(;;). E.g., for (let fn = lambda(n) { ... fn(...) ... }; testExpr; updateExpr) ... Also, for (let i = 0, j = i + 1; ...) ... But the modifications needed to make these work are pretty straightforward. Then again, I'm not sure it matters. I think the real problem here is that the updateExpr, as written by the user, is (or, rather, usually is) an assignment, and you should give the user what the user asked for. I also find it odd that { let x = 0; for (; x n; x++) ... } should have different behavior than for (let x = 0; x n; x++) ... -Jon ___ Es-discuss mailing list Es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: return when desugaring to closures
On Mon, Oct 13, 2008 at 11:43 AM, Mark S. Miller [EMAIL PROTECTED] wrote: On Mon, Oct 13, 2008 at 8:05 AM, David-Sarah Hopwood [EMAIL PROTECTED] wrote: for (var ...) implicitly introduces a block whether or not it is a substatement. This is a wart of C++/C99/Java syntax that we have to live with, since too much code relies on it. Yes, but how do we live with it? The only currently allowed case, var as above, is no problem, since it hoists to the function body anyway. But what about let. Do we all agree that in for (let x = ...) {...x...} ... x ... the x after the for loop does not refer to the x defined by the for loop? Yes. Definitely. In that case, no problem with for being a SubStatement. A remaining interesting question is whether the for loop reassigns to a single per-for-loop-entry x, or whether it initializes a fresh per-iteration x. If the for loop body has a closure that captures x, it makes a difference. I recommend the per-iteration view. I like your intention here -- I brought up the iteration variable / closure issue earlier in the thread -- but this seems rather messy. In the 'var' case, x must be the same throughout, no? function foo() { for (var x = ... ) { ... x ... } ... x ... } But then it becomes extremely awkward for the 'let' or 'const' case to use a fresh variable on every iteration. It ties the semantics of 'for' to its initialization clause in a very strange way. -Jon ___ Es-discuss mailing list Es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: return when desugaring to closures
On Mon, Oct 13, 2008 at 12:47 PM, Mark Miller [EMAIL PROTECTED] wrote: On Mon, Oct 13, 2008 at 9:13 AM, Jon Zeppieri [EMAIL PROTECTED] wrote: But then it becomes extremely awkward for the 'let' or 'const' case to use a fresh variable on every iteration. It ties the semantics of 'for' to its initialization clause in a very strange way. I think it falls out of the natural desugaring of for to lambda with no special cases. The var itself causes its own hoisting and joining. Sorry -- I must be particularly dense today. What desugaring do you have in mind? -Jon ___ Es-discuss mailing list Es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: return when desugaring to closures
On Mon, Oct 13, 2008 at 6:34 PM, Brendan Eich [EMAIL PROTECTED] wrote: On the contrary, what's magical is when one stores i in elements of an array, or calls setTimeout (example in https://bugzilla.mozilla.org/show_bug.cgi?id=449811) , and the results are all the last value of the loop variable. This has been a frequent source of confusion and complaints -- a bug, in short. Yes, and binding a fresh induction variable on every iteration makes sense for a 'for-each' loop (as in the bug report you cited), where the user is not in charge of updating the induction variable by means of explicit assignment. In a plain 'for' loop, however, it *is* magic if an assignment results in a fresh binding. And it's unexpected magic. Mark said that there was a desugaring for 'for' to 'lambda,' without special cases, where this all works out, but I haven't been able to figure out what rewrite he had in mind. Doing it the way Mark proposes fixes the bug, and has no other bad effects that I can see (but we'll have to implement and user-test to be sure). Turning an assignment into a non-assignment is bad. I could be convinced, though -- do you want to try and make the case for why there should be a fresh variable per iteration with some concrete examples? https://bugzilla.mozilla.org/show_bug.cgi?id=449811 Like I said, it makes sense for 'for-each.' -Jon ___ Es-discuss mailing list Es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: return when desugaring to closures
On Mon, Oct 13, 2008 at 7:39 PM, Brendan Eich [EMAIL PROTECTED] wrote: On Oct 13, 2008, at 4:14 PM, Jon Zeppieri wrote: Yes, and binding a fresh induction variable on every iteration makes sense for a 'for-each' loop (as in the bug report you cited), where the user is not in charge of updating the induction variable by means of explicit assignment. In a plain 'for' loop, however, it *is* magic if an assignment results in a fresh binding. Why is the assignment operator relevant? The question is the binding scope of i in for (let i = 0; i N; i++) ... How is scope the issue? As far as I know, we don't disagree about scope. The assignment I'm referring to, in this example, is the 'i++' part. Mark is proposing that this does not mean increment i by one, but rather rebind i with the value of i+1 -- which is completely different and not what the user wrote. No curly braces required, we already have this in JS1.7+ and the let is scoped to the for head except for the initializer of i (you can write let i = x, j = y; too -- x and y are evaluated in the outer scope). There's scope magic in this form even though it uses = for assignment and creates only one block scope for the loop, no how many times the loop iterates. I think you misread my message. We do not disagree at all about the scope of the initialization clause, but rather the meaning of the update clause. This is why the 'for-each' loop is not problematic; it doesn't have an update clause. And it's unexpected magic. Users differ on this point, but we've had long-standing confusion and complaints about closures capturing the last value of i in let a = [1,2,3,4]; let b = []; for (let i = 0; i a.length; i++) b[i] = function () { return i*i; } and the like. Getting 16 back from b[0]() is unexpected bad magic. I understand this, but I don't see how the answer is to change the meaning of 'i++' when used in the update clause of a 'for' loop. Users may be modeling closures as capturing bindings, not scope chains of mutable objects, one per for (let...) statement or explicitly braced block. If so, could we make let declaration capture this way? Again, I'm proceeding from real users' complaints, not idle wishes. Mark said that there was a desugaring for 'for' to 'lambda,' without special cases, where this all works out, but I haven't been able to figure out what rewrite he had in mind. Tail-recursive lambda rewrite of a C-style for loop should be easy for you :-P. That's not the point. I'm talking about a rewrite from 'for' to 'lambda' that satisfies the following properties: 1) for (var i = 0; i len; i++) ... continues to mean what it means in ES3. 2) for (let i = 0; i len; i++) ... has the proper scope for 'i' (which you reiterated above), *and* 'i' is rebound -- not mutated -- on each iteration. 3) The rewrite rules are the *same,* regardless of whether it's a for (var ...) or a for (let ...) loop. At least, that's what I took Mark to mean. He can correct me if I'm wrong. -Jon ___ Es-discuss mailing list Es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Ye olde arguments argument (was: Topic list - pending changes and issues for the ES3.1 spec)
On Mon, Sep 15, 2008 at 4:18 PM, Jorge Chamorro [EMAIL PROTECTED] wrote: El 14/09/2008, a las 21:30, Mark S. Miller escribió: The arguments object itself is often passed in order for function F to give function G access to the argument list F with which was called. This seemingly innocent operation should not also inadvertently provide G with the ability to call F. F might otherwise be encapsulated within some larger abstraction. Hmm, the problem is 'callee' being a property of 'arguments' ? or the functionality that 'callee' provides ? IOW, could we have instead a ('standalone') 'callee' property (that isn't to be innocently passed on) ? ...as a property of what? Any magically bound variable breaks TC. The expression callee should have the same meaning as (function() { return callee; })() ...and it clearly does not. ___ Es-discuss mailing list Es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Ye olde arguments argument (was: Topic list - pending changes and issues for the ES3.1 spec)
On Mon, Sep 15, 2008 at 5:13 PM, Jorge Chamorro [EMAIL PROTECTED] wrote: El 15/09/2008, a las 22:32, Jon Zeppieri escribió: IOW, could we have instead a ('standalone') 'callee' property (that isn't to be innocently passed on) ? ...as a property of what? The activation object of the execution context. Don't even get me started on activation 'objects'... Mark, didn't you propose eliminating that language from the spec? (Yup. https://mail.mozilla.org/pipermail/es-discuss/2008-April/006062.html) I'm guessing that's not actually happening for ES3.1. -Jon ___ Es-discuss mailing list Es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: local
On Thu, Aug 21, 2008 at 11:21 AM, Peter Michaux [EMAIL PROTECTED] wrote: On Thu, Aug 21, 2008 at 6:31 AM, Brendan Eich [EMAIL PROTECTED] wrote: More helpful would be comments on the utility of let blocks (a.k.a. let statements) and let expressions. Also comparisons to the several let forms in Scheme (Jon Z. posted something a while ago on this topic). I was reading the resulting ticket a few days ago. http://bugs.ecmascript.org/ticket/375 I think that the let statement let (x = 2, y = x) { print(y); } should desugar to exactly (function(x, y) { print(y); })(2, x) Also the let expression z = let (x = 2, y = x) x + y; should desugar to exactly z = (function(x, y) x + y)(2, x); The reasons for these particular desugarings is this is exactly what JavaScript programmers are writing today. It is common to see something like the desugared let statement above when looping and attaching event handlers to DOM elements, for example. I also think that since the name is let that the above desugaring makes sense as the closest analogy to Scheme's let. It doesn't make sense to me to have JavaScript's let be Scheme's let* or letrec. All these lets are purely sugar coatings and I'm not opposed to having Scheme's let* and letrec added to JavaScript as they introduce even sweeter sugar for some situations. I suppose let* would need to be renamed. Peter (That's now twice I sent this message from the wrong email address. Sorry about that. I'm replying only to the lists now.) Just to be clear about this: my comments were directed at the claim that let is the new var. It seemed that one of the design goals of the let *declaration* was that it should be a drop-in replacement for var, only with block scoping. That would require (in Scheme terms) letrec*-like semantics. Given let x = 2, y = x * 2; ... the let-bound x would have to be visible to y's initializer. And given let fn = function(n) { if (n === 0) return 1; else return n * fn(n - 1); }; ... the 'fn' on the right hand side would refer to the let-bound value (and not to something in the enclosing scope). That said, I happen to like plain let semantics. But if we use those semantics, then let is certainly not the new var. Your comments above are about let statements and expressions. Since they have no 'var' analogue, the same considerations do not apply. However, it would be very odd to use letrec* semantics in one case and let semantics in the others. So, here is a suggestion that, I am sure, no one but me will like: drop let declarations and *only* include let statements and expressions. Give them let semantics. Maybe this is only true of me, but if let statements were in the language, I would never use let declarations, anyway. The advantage of the statement and expression forms is that they make the scope of the let-bound variables explicit. -Jon ___ Es-discuss mailing list Es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss