Re: Operating with arbitrary timezones

2016-08-06 Thread Jon Zeppieri
On Sat, Aug 6, 2016 at 4:27 AM, Alexander Jones  wrote:

> 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

2016-08-05 Thread Jon Zeppieri
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

2016-08-05 Thread Jon Zeppieri
On Fri, Aug 5, 2016 at 6:21 PM, Alexander Jones  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
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Operating with arbitrary timezones

2016-08-05 Thread Jon Zeppieri
On Fri, Aug 5, 2016 at 5:58 PM, Alexander Jones  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.
>
> 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

2016-08-05 Thread Jon Zeppieri
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

2012-01-20 Thread Jon Zeppieri
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

2012-01-20 Thread Jon Zeppieri
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

2012-01-19 Thread Jon Zeppieri
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

2012-01-12 Thread Jon Zeppieri
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

2012-01-12 Thread Jon Zeppieri
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

2012-01-12 Thread Jon Zeppieri
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

2011-06-30 Thread Jon Zeppieri
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

2011-05-25 Thread Jon Zeppieri
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

2011-05-25 Thread Jon Zeppieri
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

2011-05-24 Thread Jon Zeppieri
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

2011-05-24 Thread Jon Zeppieri
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

2011-05-21 Thread Jon Zeppieri
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

2011-05-21 Thread Jon Zeppieri
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

2010-11-05 Thread Jon Zeppieri
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

2010-11-05 Thread Jon Zeppieri
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

2010-11-04 Thread Jon Zeppieri
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

2010-11-04 Thread Jon Zeppieri
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

2010-11-04 Thread Jon Zeppieri
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

2010-11-04 Thread Jon Zeppieri
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

2008-12-09 Thread Jon Zeppieri
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

2008-12-06 Thread Jon Zeppieri
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

2008-12-06 Thread Jon Zeppieri
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

2008-12-05 Thread Jon Zeppieri
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

2008-12-04 Thread Jon Zeppieri
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

2008-12-04 Thread Jon Zeppieri
[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

2008-12-04 Thread Jon Zeppieri
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-03 Thread Jon Zeppieri
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-03 Thread Jon Zeppieri
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

2008-12-03 Thread Jon Zeppieri
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

2008-12-03 Thread Jon Zeppieri
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

2008-12-03 Thread Jon Zeppieri
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?

2008-12-02 Thread Jon Zeppieri
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?

2008-12-02 Thread Jon Zeppieri
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?

2008-12-02 Thread Jon Zeppieri
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?

2008-12-02 Thread Jon Zeppieri
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)

2008-10-14 Thread Jon Zeppieri
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

2008-10-13 Thread Jon Zeppieri
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

2008-10-13 Thread Jon Zeppieri
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

2008-10-13 Thread Jon Zeppieri
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

2008-10-13 Thread Jon Zeppieri
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)

2008-09-15 Thread Jon Zeppieri
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)

2008-09-15 Thread Jon Zeppieri
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

2008-08-21 Thread Jon Zeppieri
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