Re: importModule followup

2008-08-18 Thread Brendan Eich
On Aug 18, 2008, at 8:35 AM, Brendan Eich wrote:

 Scripts are synchronously loaded today, but browsers are working on
 async loading techniques, and IE promulgated the defer attribute into
 HTML5.

Er, into HTML4.

(Coffee time! ;-)

/be
___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Picking property by attribute

2008-08-18 Thread Brendan Eich
On Aug 18, 2008, at 9:28 AM, Yuh-Ruey Chen wrote:

 OK, with the advent of ES-Harmony, I have no clue whether the language
 will support iterators (and maybe generators)

We talked about these in Oslo. My notes say generators received  
favorable comments, with the thought from Mark Miller that the  
introductory keyword might better be 'generator' than 'function'.  
These were never a bone of contention between factions, AFAIK.


 or catch-all methods.

These required the meta namespace in ES4 as proposed.


 I know that namespaces are out.

Then you do have a clue about catchalls as proposed :-/.

/be

___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Remarks about module import

2008-08-18 Thread Brendan Eich
On Aug 18, 2008, at 4:55 PM, David-Sarah Hopwood wrote:

 I really like the general approach and the simplicity of Ihab's  
 proposal.
 Also I strongly agree that a module should *not* implicitly capture
 the lexical scope in which it is imported.

I don't think anyone proposed any such thing. Do you?


 I'm not sure why 'provide' needs new syntax, though.

Syntax is (a) often good UI; (b) special form expression where  
there's no library way to say what the special form says.

Why should everything be lambda-coded?

What if I change your bindings for module and provide? (Maybe I  
can't; please explain why not.)

I'm not being snarky (or not merely ;-). The pre-Harmony extreme of  
no new syntax, ever is dead. Asking whether new syntax pays for  
itself is ok, but the question becomes vacuous when the only  
demonstration against new syntax begs questions about usability and  
integrity.

/be


___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: local

2008-08-21 Thread Brendan Eich
On Aug 21, 2008, at 6:54 PM, Mark S. Miller wrote:

 On Thu, Aug 21, 2008 at 3:07 PM, Brendan Eich [EMAIL PROTECTED]  
 wrote:
 [...] A strict mode or similar [...]. The greater its distance  
 from the standard mode,

 A nit: Please let's start referring to the opposite of strict mode as
 non-strict mode. Once these become official, they will both be
 standard.

Ok!

/be

___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: return when desugaring to closures

2008-08-21 Thread Brendan Eich
On Aug 21, 2008, at 7:26 PM, Peter Michaux wrote:

 It works in practice as context of syntax sometime matters.

Context matters in many ways in JS and other languages.


 This is definitely an example of the same syntax having semantically
 different meaning (actually opposite meanings)

The syntax is not the same because of the left-hand side of  
assignment (=) vs. right. Mutation in JS is a concern; you have to  
know whether you're assigning or using a variable; you have to pay  
attention to context.

 which was an objection
 to the use of return in an let statement if a let statement desugars
 to a function-expression call.

I anticipated this when I wrote in an earlier reply:

Different semantics should have distinct syntax; similarity or
symmetry may motivate reuse of syntactic forms or ideas. Here, there
is no function to return y from, to be assigned to z. You could say
let desugars, but it doesn't say what it means.

You are proposing the *same* semantics for different syntax (let vs.  
function expression that's called right away). Destructuring patterns  
use the same (or similar, in the case of the object shorthand) syntax  
for related (complementary, symmetric about =) semantics. See the  
difference?

That 'return' is the common syntax inside your let-as-lambda-call is  
not the source of similarity, since the outer syntax (let vs.  
function) is dissimilar. The cognitive load comes from the question:  
where does return go?, since it is a control flow break. The  
Smalltalk page I linked to earlier talks about this.

Another example in favor of similar syntax for similar or related use- 
cases: JS uses function forms in expressions and definitions. The  
contexts and effects differ, but the similarity motivates syntax re-use.

Not so the case with the same (not similar, same -- desugaring)  
semantics for your different outer syntaxes, especially when the cost  
is loss of pellucid return, break, continue, plus the bigger loss of  
purely lexical scope, which by contrast let in JS1.7 provides.

/be
___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: local

2008-08-22 Thread Brendan Eich
On Aug 21, 2008, at 10:10 PM, Breton Slivka wrote:

 In the case of let statements, as I understand it, the current
 proposal, and how let works in firefox is that

  let (x = 2, y = x) {
  print(y);
  }

 desugars to

 {
 let x = 2, y = x;
 print(y);
 }

No, because in the latter, as for var in a program or function body,  
let x is hoisted to the top of the block, so y's initializer x is not  
the value of the outer x, but the undefined initial value of the  
hoisted inner x.

So let statements really are different from let declarations in blocks.

New let forms may look spooky or useful, depending on your language  
background. Schemers tend not to be spooked; folks who started with  
JS, Java, C++ or C may bolt ;-).

/be
___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Attribute defaults for Object.defineProperty

2008-08-23 Thread Brendan Eich
On Aug 22, 2008, at 11:53 AM, David-Sarah Hopwood wrote:

 Allen Wirfs-Brock wrote:
 Michael Haufe [mailto:[EMAIL PROTECTED] said:
 Although I'd prefer to control Deletable separately from Fixed,

 Using a single state to control deletability, attribute  
 mutability, and
 property transformation/replacement is a compromise.  There may be  
 some
 situations where somebody would really like to control these  
 separately
 but it is probably a pretty limited use case.

 If you can set attribute mutability, then you can set the Delete  
 attribute.

 If you can set the Delete attribute, then you can delete the property
 (and its current attributes).

 If you can delete the property, then you can recreate it with  
 different
 attributes.

 So, there is neither a security nor an expressiveness argument for  
 making
 any distinction between these rights. An argument for separating them
 would have to be based on convenience (but it seems less  
 convenient, not
 more), or on preventing inadvertent, non-malicious changes, or  
 possibly
 on efficiency (but these operations are probably not common enough for
 that to be significant).

Agreed on all points. The prototype-based language Wheat started with  
what looked like Unix owner/group/other permission bits, but the  
nonsense or dangerous combinations were eliminated (if my memory  
serves). We should not even flirt with this kind of false orthogonality.

That's why DontDelete was not a bad name in its day. Even in ES1 or  
the prior JavaScript and JScript implementations had something like  
it (SpiderMonkey's name is permanent).

It's not that configurable is bad, even if overlong. It is less  
concrete in terms of what is controlled and why. Concrete names are  
generally better.

No CanMod, though -- I was flashing back to 6BIT charsets on DEC 36- 
bit processors ;-).

/be

___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Es-discuss - several decimal discussions

2008-08-23 Thread Brendan Eich
On Aug 23, 2008, at 8:44 AM, [EMAIL PROTECTED] wrote:

 On Sat, Aug 23, 2008 at 1:49 AM, Mike Cowlishaw [EMAIL PROTECTED]  
 wrote:
 Finally, I'd like to take a poll: Other than people working on  
 decimal
 at IBM and people on the EcmaScript committee, is there anyone on  
 this
 list who thinks that decimal adds significant value to  
 EcmaScript? If
 so, please speak up. Thanks.

 Decimal arithmetic is sufficiently important that it is already
 available in all the 'Really Important' languages except ES
 (including C, Java, Python, C#, COBOL, and many more).  EcmaScript is
 the 'odd one out' here, and not having decimal support makes it
 terribly difficult to move commercial calculations to the browser for
 'cloud computing' and the like.

 Decimals in Java are implemented at the library level, as
 java.math.BigDecimal. There is no expectation that intrinsic math
 operators work on them. Is this approach valid for ES; if not, then
 why not?

See

http://jroller.com/cpurdy/entry/the_seven_habits_of_highly1  
(especially the first comment, by Bob McWhirter)

also see

https://bugzilla.mozilla.org/show_bug.cgi?id=5856

All linked from the still-useful

http://wiki.ecmascript.org/doku.php?id=discussion:decimal


 Implementing decimals at the library level has the advantage that they
 can be deployed today, as functional (if slower) ES code, and
 optimized later on by a native implementation with no loss of
 compatibility.

http://gwt-math.googlecode.com/svn/trunk/gwt-math/src/main/resources/ 
com/googlecode/gwt/math/public/js/bigdecimal.js

;-)


 After all, it will be several years before the next ES
 version becomes reliably available on consumers' browsers.

Several years or less than a year from final spec, depending on the  
vendor's commitments to standards.


 Does this
 manner of easing migration inform the approach being taken?

Not really. If you want GWT, use it. If you want a library, they are  
out there. The problem is making a new type in ES3.1's spec work,  
both now and in the future when operators are added (so we can avoid  
the laughable but totally predictable outcome Bob McWhirter cited in  
Purdy's blog).


 Conversely, if one is to add support for the intrinsic math operators
 on decimals, does the required work generalize easily to arithmetic on
 complex numbers and matrices?

We might hope to know by looking at other languages, but really,  
doing the work in the context of backward JS compatibility is  
required. So again, doing what Sam is doing in developing patches  
against open source JS implementations seems at least as valuable as  
trying to spec Decimal quickly, making it law, and then hoping it  
works out in the future *and* somehow leads to a taller numeric tower.


 Will the addition of complex numbers and
 matrices require more difficult work about how they interoperate with
 existing number representations (including, at that point, decimal
 numbers)? How, if at all, does this inform the present discussion?

You might find

http://wiki.ecmascript.org/doku.php?id=proposals:generic_functions

interesting. Obviously not a live proposal, but if we ever want  
operators, I'm still in favor of multimethods instead of hardcoding.  
The current untestable spec can't stand much more complexity in its  
runtime semantics. If we ever get complex numbers, quaternions, etc.,  
they should come by users defining operator multimethods after the  
committee has retired in victory to the same Valhalla where Dylan and  
Cecil are spoken :-/.

/be

___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Use of redundant var

2008-08-23 Thread Brendan Eich
On Aug 23, 2008, at 8:23 AM, Fergus Cooney wrote:

 Another use I have for redeclaring variables is when I want to  
 reuse the
 name but there's a clear separation between the previous use and  
 the new
 use. For example, I might have a variable to amass a bunch of html  
 snippets
 and then stick them in a div. I'll redeclare that variable again if  
 I'm
 doing separate content for another div. It makes it explicit that  
 there's no
 carry-over from above. Also, as I'm the declare-everything-first  
 type, it
 also helps if I decide rearrange the code.

That last point is a great one.

We did talk about redundant declarations when discussing strict mode.  
IIRC we agreed not to punish them, mainly for the last reason and the  
consequent abundant use of var in several paragraphs of code where  
the vars have the same name and hoist to the same body scope, and  
nothing's formally wrong with the code.

We can't have strict mode exact an inordinate migration tax, or it  
won't be used. We shouldn't make it too pedantic, or it will either  
not be used, or else waste programmer energy on non-problems or  
hypothetical problems.

/be

___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Es-discuss - several decimal discussions

2008-08-24 Thread Brendan Eich
On Aug 23, 2008, at 5:45 PM, [EMAIL PROTECTED] wrote:

 On Sat, Aug 23, 2008 at 11:30 AM, Sam Ruby [EMAIL PROTECTED]  
 wrote:
 Having Decimal.parse(2) + 3 produce 23 is not what I would call  
 fail
 fast, as that is a term I would typically use for throwing an  
 exception or
 the like.

 Point well taken. Does Maciej's followup regarding valueOf throwing
 solve the problem?

It forces would-be Decimal users to call Decimal.add(Decimal.parse(s)  
+ 3) (let's say s may or may not be 2 or 2). Is that a solution for  
ES3.1? It's user-hostile instead of future-hostile.

Can we not do better, especially by not overconstraining the problem  
by subjecting its solution to the ES3.1 goals and schedule?


 Were ES designed, back in 1995, to be the language it has become, and
 were there time back then to have thought about how the builtin
 arithmetic and comparison generalizes to mixtures of decimals,
 arbitrary precision integers, complex numbers, matrices and
 polynomials, I would agree with you unequivocally. As matters stand,
 I'm not so sure.

I've been through as many what-if's and might-have-been's as anyone.  
JS clearly had too much implicit magic -- Perl-envy, if you will --  
to be as neatly extensible as we want, in hindsight.

EIBTI, the Pythonistas say. But this need not mean explicit method  
calls instead of operators for any numeric extension, since that's  
pretty much unusable (except under SOX mandate :-/).

We've often cited EIBTI in ES4 working group meetings. In general I  
daresay the TC39 committee is more in favor of avoiding implicit  
magic, especially conversions, now than ever (E4X, ECMA-357, is full  
of it, and it's a mess). But this doesn't mean that throwing when a  
Decimal is used in any not-guaranteed-to-be-numeric operand context  
is good.


 It would not be wise for equality operators, in particular, to
 start throwing exceptions.

 Could these operators simply be consistent with === for any user
 defined library type, and something else (a .equals() operator, say)
 be used to define value equality?

That's incompatible, and the double-dispatched (for dyadic operators)  
method mapping is something we'd like to avoid in the future  
(wherefore multimethods).


 Once again, Java faced this same problem in adding BigDecimal -- and
 Java is strongly typed and so arguably had more leeway to add rules
 that make it clearer to programmers what was going on. Yet their
 solution was to simply create classes at the library level.

BigMistake, as Cameron blogged. Java failed, C# ruled here.


 I think the Java analogue is instructive. In Java, primitives and
 objects are distinct.

That's a botch, one I copied in a hurry in 1995 and regret. I should  
have stuck to the Self and Smalltalk sources of inspiration, but JS  
had to look like Java and it was easier both to implement, and to  
think about JS/Java bridging (LiveConnect, so-called), if I  
distinguished primitive string, boolean, and number from their object  
wrapper types.


 BigDecimal was apparently a clumsy enough entity
 that it was found to need implementation as a constructed object.

This apparently backward-reasoning phenomenology is flawed.  
Implementors can work harder so programmers don't have to. There's no  
technical reason that decimal has to be a non-primitive in any  
language that distinguishes primitive types from first-class object  
types, any more than there is for strings to be non-primitive.


 In
 ES, everything is an object yet there are primitive types; this means
 that, when faced with a newly required constructed object type, we are
 tempted to slip it in as a new primitive. In the absence of extensive
 planning done back in the mid 1990s, I submit that the temptation is
 to be resisted.

What extensive planning do you mean? Oh, the lack of it when I  
created JS.

Sorry, this is bogus arguing too :-|. Five-year plans are no  
guarantee of success. Utopia is not an option. Lots of underused  
languages have over-planned designs and nevertheless have big  
problems (other than lack of users).

Anyway, languages that do succeed in gaining users inevitably grow.  
Growing a language is hard but possible. Python grew, including in  
its numeric model and operators. In spite of harsher backward  
compatibility constraints, so too can JS.

IEEE double is not the only conceivable number type, and indeed 32- 
bit int and unsigned int show through in places in JS (bitwise  
operators, array length). I'm not in favor of more machine types. But  
I think making more BigMistakes with methods only, no operators, is  
guaranteed to keep IEEE double the only number type that's actually  
used by most real-world JS programmers.

/be

___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Es-discuss - several decimal discussions

2008-08-24 Thread Brendan Eich

On Aug 23, 2008, at 8:23 PM, Sam Ruby wrote:


The remainder of the quote that was relayed to me was that spec'ing
the operators would not be hard.  I took it upon myself to
refamilarize myself with spider monkey and implement these operators,
and despite it being a decade or so since I've done any serious C/C++
coding was able to complete that task in a long weekend.


You know that I'm glad you're doing this. Doesn't mean it's going to  
make 3.1, or that it must.




I've since started updating the spec, and the changes are very
straightforward and contained.  You can see for yourself, most of the
changes are already in there.


I will look when time permits, before the next TC39 meeting.



Given this, the way I would like to proceed is towards a full and
complete proposal to be ready in time for people to review for the
Redmond meeting.  It may very well need to be scaled back, but I  
would
much rather be in a position where the edit requests that came  
out of

that meeting were in the form of prune this rather than once again
be presented with investigate that and report back.


How would a response of take the time you need, and we'll track it
for Harmony; 3.1 is otherwise all but done strike you?


Frankly, it sounds like moving the goal posts.


You think so? I respectfully disagree, and I've been in all the face- 
to-face meetings. ES3.1 started in earnest this past January, with a  
limit scope. Decimal (already in ES4 as proposed, with operators as  
well as literal syntax) was not being pushed into ES3.1 until spring- 
time, at which time 3.1 was supposed to be technically done in  
July, finalized including editorial fussing and typography in  
September, etc., for standardization at the December GA meeting.


Seems to me the push for Decimal moved some posts. Why is Decimal-or- 
a-No-vote being hung like a sword over the committee's head? What  
goes wrong if Decimal is not in 3.1, but is (especially with user- 
feedback-based improvements) in the successor Harmony edition within  
1-2 years?




When is spec freeze?  When do we need to have implementations
complete?  Are we planning to have these implementations usability and
field tested?  Will adequate time be allowed to factor in feedback
that is received from these tests?


Let's get the implementations done and we'll see. There's no  
deterministic top-down command -and-control schedule here. For the  
open source implementations, the main thing is to get into nightly  
builds, get docs and blogs educating users, gather bug reports.




I'm writing the spec.  I've written one implementation -- or more
precisely a binding to an implementation that has been well tested and
made available under a very liberal license.  I've run the performance
tests you asked me to run.  I'm ready and willing to convert the
existing decNumber test suite over to whatever format is desired; I'm
also ready and willing to write additional tests to cover the ES
specific binding to these functions.


We should talk about landing your patch on Mozilla elsewhere. IIRC  
Rob Sayre asked for a few things in the bug and I haven't seen your  
response (I may have missed it; been busy lately).




The meanings of operators when all of the operands are decimal are
well specified by IEEE 754R.  The meaning of equality in ES3 is a bit
arcane, and we've worked through that.  My SpiderMonkey implementation
provides access to decNumber's compareTotal method, and Object.eq
(something Doug and Mark feel is necessary for other reasons) can be
defined in such a way as to make use of that function.


What's the Object.eq issue? I must have missed an 8am 3.1 call. :-/



What's left is figuring out is the syntax for constructing decimals
from strings (Decimal.parse sounds fine to me, how about you?), and
from binary64 floating point numbers (Number.toDecimal sounds fine to
me, how about you?).


I like those names, FWIW.



  And to decide whether binary64 numbers get
converted to decimal128 when they are mixed, or if it is the other way
around.


That is important to get right. Igor Bukanov and I both sounded off  
on this list as against any mixing of decimal128 and binary64 that  
degraded toward binary64. So I'm pleased as punch with your new  
thinking.




  I was originally pursing the latter, but based on feedback,
I'm seriously considering the former -- with the proviso that the
conversions be exact and correct rounded, to the limits of the
precision supported by decimal128.  This approach not only has the
advantage of being exact and correct, it also obviate the need for
use decimal.


Maybe, except writing 123m all over is enough of a drag that most  
people won't. There still could be a case for 'use decimal'.


How's the new approach (contagious decimal128) working out in the code?

/be___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Es-discuss - several decimal discussions

2008-08-24 Thread Brendan Eich
On Aug 24, 2008, at 12:51 AM, Maciej Stachowiak wrote:

 But this doesn't mean that throwing when a
 Decimal is used in any not-guaranteed-to-be-numeric operand context
 is good.

 Actually, throwing from valueOf would have the opposite effect.

Of course, and my not- was a thinko. I meant guaranteed-to-be- 
numeric. Having memorized a lot of ES3, including where the  
preferredType hint is not number, I was not trying to make the  
opposite point within the same mail message.

We could throw from valueOf, but at least you and I agree it would be  
better to avoid any such a seemingly-rushed, library-only, user- 
hostile Decimal. Waldemar and I said so at the Oslo meeting, and Sam  
agrees.

I am interested to see what Sam can pull off, in code more than spec.  
I don't doubt the spec can be done, given design decisions from IEEE  
P754 and some freedom to match JS design impedance. I'm concerned we  
won't have time to give such a purportedly user-friendly Decimal  
sufficient user testing.

/be

___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Es-discuss - several decimal discussions

2008-08-24 Thread Brendan Eich
On Aug 24, 2008, at 6:18 AM, Sam Ruby wrote:

 A modest
 request: if the code could be reviewed and feedback provided to me
 with sufficient time for me to address the comments and the code to be
 integrated into a nightly build, by default disabled, in time for the
 Redmond meeting, I would appreciate it.

Set the review flag to my bugzilla id -- othewise I won't see it in  
my request queue, and I'll probably forget to go review it on my own.  
Thanks.


 Let's posit for the moment that adding two nickles and calling
 toString() on the result produces 1.10

Where'd the buck come from? ;-) Ok, I'm with you so far...


 Furthermore assume that 1.10m  1.09m and that 1.10m  1.11m.

 Given the above, as well as your knowledge of ES history, what would
 you expect the results of evaluating the following two expressions to
 be:

   1.10m == 1.1m

true.


   1.10m === 1.1m

true, but there's a weak case for false if you really insist that the  
significance is part of the value. If we make the result be false,  
then people who advocate always using === instead of == to avoid  
implicit conversions would be giving bad advice to Decimal users. I'm  
sticking with true for the reason given below.


 Depending on your answers, there may be a followup question.

Guy Steele, during ES1 standardization, pointed out that some Lisps  
have five equality-like operators. This helped us swallow === and !==  
(and keep the == operator, which is not an equivalence relation).

Must we go to this well again, and with Object.eq (not an operator),  
all just to distinguish the significance carried along for toString  
purposes? Would it not be enough to let those who care force a string  
comparison?

/be

___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Look Ma, no this (was: ECMAScript Harmony)

2008-08-24 Thread Brendan Eich
Polls are not so good, compared to reasons. Could you give your  
rationale and talk about the trade-offs, in your experience?

/be

On Aug 24, 2008, at 7:36 PM, Peter Michaux wrote:

 On Sun, Aug 24, 2008 at 6:05 PM, Brendan Eich [EMAIL PROTECTED]  
 wrote:
 On Aug 24, 2008, at 4:09 PM, Mark S. Miller wrote:

 [snip]

 Others on this list should comment on class-private vs. instance-
 private.

 If this is just a poll then I'm all for instance-private.

 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: Es-discuss - several decimal discussions

2008-08-25 Thread Brendan Eich
On Aug 24, 2008, at 10:02 PM, Mark S. Miller wrote:

 Let's say you did that -- make a special case for NaN but not for -0.
 Let's say you use this Map to build memoize. Now let's say someone
 writes a purely functional function F such that F(0) is 3 and F(-0) is
 7. Let's say G is memoize(F). Would you find it acceptable for G(0) to
 sometimes yield 3 and sometimes 7?

I'd file a bug, or find a better memoizer :-). Quality of  
implementation eager beavers can use Math.atan2 to tell -0 from 0,  
just as they can use isNaN or x !== x.

Yes, this is gross. I'm in favor of Object.identical and  
Object.hashcode, maybe even in ES3.1 (I should get my act together  
and help spec 'em). Just not particularly on account of Decimal, even  
with equated cohort members. I still agree with Sam. And as  
always,hard cases make bad law.

/be
___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Look Ma, no this (was: ECMAScript Harmony)

2008-08-25 Thread Brendan Eich
On Aug 24, 2008, at 8:40 PM, Peter Michaux wrote:

 Polls are not so good, compared to reasons. Could you give your  
 rationale
 and talk about the trade-offs, in your experience?

 You summed it up nicely with the hat trick:

 It's a nice hat trick: privacy, higher integrity, and semantic reuse
 all in one.

 I'm not sure there will be anyone who can explain that any one OOP
 system is right and the others are less right. That is what I imagine
 will make consensus on this topic very difficult.. Every OOP language
 has a different set of OOP features so there doesn't appear to be an
 objective (ha!) winner after decades of programmers exploring OOP. The
 fact that this is really a subjective issue is why your initial
 request for comments seemed somewhat appropriate for a poll. It is a
 what do you like question.

And yet you go on to make a great non-aesthetic case, with particular  
and pointed reasoning. (The delegation boilerplate for Java has-a  
cases scores!) Thanks. I'm still inclined the same way as you and  
Mark (and I believe Waldemar, at least at Oslo). IP+ZI FTW! ;-)


 I've talked about both privacy and inheritance when you only requested
 about privacy but the two issues are closely related.

Indeed. Thanks again for the thoughtful response,

/be

___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Look Ma, no this (was: ECMAScript Harmony)

2008-08-25 Thread Brendan Eich
On Aug 24, 2008, at 9:44 PM, Kris Zyp wrote:

 I am surprised this is up for debate, I would also think that we  
 would want
 instance-private by default.

We can debate lots of things, some that might actually be in play.  
AFAIK this one is not decided in the committee (it's way too early),  
but IP does have some strong proponents.

AS3, JScript.NET, and Waldemar's original ES4/JS2 work all had CP.  
Java has CP. So do C++ and C#. It should not come as a surprise,  
therefore, if CP has at least to be dealt with by some rationale for  
IP over against CP. Smalltalk rules won't cut it ;-).

I'm happy to have a little debate on this topic, given the different  
precedents. I'm wondering why you think there's no question.

/be
___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Look Ma, no this (was: ECMAScript Harmony)

2008-08-25 Thread Brendan Eich
On Aug 25, 2008, at 12:34 AM, Peter Michaux wrote:

 On Sun, Aug 24, 2008 at 9:44 PM, Kris Zyp [EMAIL PROTECTED] wrote:

 Desugared from:

 class Point {
   private var x = Math.random();
   function getX(){
   return this.x;
   }
   ...
 }

 Is there any need for the this.? Some languages allow this.x to
 get out from under the shadow of a local x inside getX. I don't
 think it is necessary to be able to escape such shadowing and actually
 increases confusion. If a method is many lines long then the reader
 may forget that x is local and not the instance variable. I would
 just call the local variable locx or xx or something different. I
 would actually rather see the this. shadow escaping be disallowed.

That might be a good idea.

The bigger question is whether |this| remains at all. The desugarings  
we tend to write on whiteboards use |let self = ...| or similar and | 
self| as the new |this| -- but of course that might collide with a  
necessary inner or outer name. It would be better to gensym the name,  
but who has time at a whiteboard?

To refer to the instance in the sugared language, and there are valid  
use-cases for doing so, we should use |this|. There's no point in  
introducing a new keyword. Which gets to a point you raise later,  
about var in class being confusing. If class is the new, higher  
integrity constructor function that induces instance-bound frozen  
methods, etc., then its syntax (by the similarity principle I  
adumbrated earlier) *should* mimic function:

class Point(x, y) { // parameters to constructor here
   let r = Math.sqrt(x*x + y*y);
   let theta = Math.atan2(y, x);
   function getX() x;
   function getY() y;
   // etc.
}

var or const could be used too, because they can be used in function  
bodies. Class body *is* constructor code. Similarity is good because  
it builds on JS programmers' knowledge of functions, but provides  
incrementally better semantics for the similar syntax. Programmers  
get the carrot, not the stick of gratuitously different syntax.

It will take more than a 2D point class to make the case, but this  
was along the lines of the Oslo discussions on the third day, to  
desugar as Mark proposed on the first (and showed in his post at the  
head of this thread).


 In the above code snip it seems that properties will be public unless
 listed as private. In the security world, whitelisting is considered a
 best practice as blacklisting can accidentally leave things out in
 public that should not be.

Not everything in JS is security-critical. JS is used in single-trust- 
domain embeddings, but even on the web, the BD programming by way of  
the security root password to the tattered just a scripting  
language constitution seems like a power-grab :-P. I mixed three  
kinds of technical politics there, but they are all relevant.  
Different parties are concerned about the common good, but we don't  
all agree on the common good.

Python and Smalltalk don't have private methods by default (or at  
all), just to pick two examples. Should classes as better  
constructors have this bias?

I'm not saying no, I reserve judgment. It seems to me much depends  
on the module system, if there is one (and there had better be, since  
in spite of being the inevitable source of addressing and loading  
semantics, the script tag is not enough for in-language modularity).


 What about the following two options:

 class Point {
private x = Math.random();
public function getX(){
return x;
};
 }

Verbose, please pick a default. Making people type private all the  
time is going to get old (if you think 'function' is too long...).


 var Point = class {
private x = Math.random();
public getX = function(){
return x;
};
 };

This shows a separable and good idea: first-class classes. BTW, you  
probably want 'const Point = class { ... }', and 'class Point...'  
should make a const binding by default (unlike a function definition  
-- another upgrade).

Another separable point to debate: resolved, classes should freely  
nest (in other classes and functions) and generate new entities each  
time they are evaluated. Just like functions (ignoring or removing  
the joined function object option from ES3).


 If only one option could be included I'd *much* prefer the final
 option as var could be changed to let so I control the class's
 scope better.

That's not to say we shouldn't have the named form of class, any more  
than we shouldn't have named functions. Named functions are a special  
form, as close to let rec as you get in JS. You can have mutually  
recursive named functions call one another freely, making forward  
refs, due to hoisting.

You also get the intrinsic name, useful for diagnostics at runtime  
and harder to infer (really guess, worst-case pick the name of the  
most relevant binding) for anonymous functions.


 In either of the last two cases, I imagine that the Point variable
 is pointing to a 

Re: Look Ma, no this (was: ECMAScript Harmony)

2008-08-25 Thread Brendan Eich
On Aug 25, 2008, at 6:39 AM, Kris Zyp wrote:

 I am surprised this is up for debate, I would also think that we   
 would
 want
 instance-private by default.

 We can debate lots of things, some that might actually be in  
 play.  AFAIK
 this one is not decided in the committee (it's way too early),   
 but IP
 does have some strong proponents.

 AS3, JScript.NET, and Waldemar's original ES4/JS2 work all had  
 CP.  Java
 has CP. So do C++ and C#. It should not come as a surprise,   
 therefore, if
 CP has at least to be dealt with by some rationale for  IP over  
 against
 CP. Smalltalk rules won't cut it ;-).

 I'm happy to have a little debate on this topic, given the different
 precedents. I'm wondering why you think there's no question.

 /be

 I'm sorry, I had misunderstood. I was thinking CP meant one  
 variable per
 class (like indicated by static), but CP means the scope of who  
 could
 access the private object property. This is a question worthy of  
 debate.
 Thanks,

Yeah, that confusion happened briefly in Oslo. Class-private vs.  
instance-private instance variables might be the long-winded solution  
to ambiguity. CPIV vs. IPIV? Yuck.

Properties of the class constructor, with appropriate attributes, AKA  
class statics, are not controversial AFAICT. There ought to be sugar.  
It might well use the static keyword.

/be

___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Es-discuss - several decimal discussions

2008-08-25 Thread Brendan Eich
On Aug 25, 2008, at 4:29 AM, Sam Ruby wrote:

 If Decimal is an object type, then typeof 1.0m == object is good
 for a couple of reasons:

 * Future-proof in case we do add a primitive decimal type, as ES4
 proposed -- a peer of double that shares Number.prototype; typeof on
 a decimal would return number. See below for the possibly-bogus
 flip side.

 What would be the upside to such an approach?  I can see the
 next-edition-of-ES-that-provides-decimal (my working assumption still
 is 3.1 whatever that may be called, others may be understandably
 skeptical) only providing a Decimal object, and with that addition the
 language with respect to decimal being considered a steady state that
 not need to be revisited in subsequent editions.

Yes, I was being a little too generous with the possibility of a  
primitive making a come-back. If we evolve by adding Decimal as an  
object typeof-type, that's it. Probably better this way in the long  
run, the operator extensions should inform our evolving thinking on  
generic arithmetic and multimethods.


 * Analogous to RegExp, which has literal syntax but is an object
 (RegExp is worse because of mutable state; Decimal presumably would
 have immutable instances -- please confirm!).

 I'd prefer if Decimal instances in ES were considered immutable and
 automatically interned.  By the latter, I simply mean that new
 Decimal(1.0) === new Decimal(1.0).

The spec should say this.

Decimal.prototype would be extensible and not sealed, however, just  
as other standard constructor prototype objects are. A bit of a  
challenge in the spec, and in implementations that make an  
unconstructed primordial instance be the class prototype, but not  
insuperable (hand-wave alert).

/be
___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Es-discuss - several decimal discussions

2008-08-25 Thread Brendan Eich
On Aug 25, 2008, at 6:45 AM, Mark S. Miller wrote:

 maybe even in ES3.1 (I should get my act together and help spec 'em).

(I will help on identical/hashcode, btw -- think we're agreeing  
vehemently ;-).)

 Just
 not particularly on account of Decimal, even with equated cohort  
 members. I
 still agree with Sam. And as always,hard cases make bad law.

 What is it you and Sam are agreeing about? I lost track.

That if we make cohort members == and ===, telling anyone who still  
wants to distinguish 1.0m from 1.00m to use compareTotal is good  
enough.

/be
___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: eq, eql, equal [Was: Es-discuss - several decimal discussions]

2008-08-25 Thread Brendan Eich
On Aug 25, 2008, at 6:58 AM, Mark S. Miller wrote:

 On Mon, Aug 25, 2008 at 6:50 AM, P T Withington [EMAIL PROTECTED] wrote:
 FWIW, as a user, I've always assumed:

 == : equal [1]

 [1, 2] == [1, 2] // yields false

This makes me sad, but some day there might be ways to attach  
multimethods (opt-in basis) that make it all better. Just a thought.

/be

___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Look Ma, no this (was: ECMAScript Harmony)

2008-08-25 Thread Brendan Eich

On Aug 25, 2008, at 12:23 PM, Peter Michaux wrote:


To refer to the instance in the sugared language, and there are valid
use-cases for doing so, we should use |this|. There's no point in
introducing a new keyword.


If there is a need to refer to the instance then this does make
sense. What would be a great success if if there is just no need for
this at all. It certainly seems possible to avoid.


I don't think so. Standard patterns of delegation (visitor, double- 
dispatched dyadic operators) must pass |this| whole and intact.




Now there is another problem: differentiating between which variables
are local to the constructor function (that is, transient and garbage
collected after the constructor function is returned (don't know the
technical name for these variables))


Temporaries.



and which are properties of the
resulting returned object.


True temporaries might need explicit block scope to avoid being  
entrained in closures.




Requiring the programmer to use both public and private as I did
below might be a solution (though you thought it is verbose) so that
it is clear which variables are part of the constructed objects.


But the private vars would not be temporary. They would need to live  
as long as the instance. It seems to me you're mixing lifetime with  
visibility.




I suggest at least a couple DOM widgets are used (e.g. tabbed pane,
dragdrop list, sortable table) as test examples when discussing class
sugar seriously. The DOM is a big part of the JavaScript world, after
all.


Great idea.

A lot of Ajax widgets, e.g. Dojo, use their own inheritance models,  
often based on copying properties (sometimes based on prototypes; in  
the case of Dojo's MI, both!). Copying is fine for a zero-inheritance  
classes-as-sugar proposal. The prototype stuff, as Kris points out,  
is different.




In ES3 a nested function is private inside the outer function. So
there is some sense of private by default already.


Lexical scope is great. You have a point.



No one seemed to response to my post in the thread about modules but
module should not equal file as HTTP is still expensive and
programmers want to concatenate and minify their scripts.


Oh, absolutely. I made the point in several posts, and Ibad picked up  
on it: addressing and loading are outside the core language. The  
inside part that's left is about how the importer names (or does not  
name) the module, how the module provides what the importer requires,  
how eagerly linking occurs, whether cycles are allowed (better  
be!), etc.


The upshot is that stuff has to be loaded already. You can't block a  
script mid-evaluation and go service events (violating run-to- 
completion or else locking up some or all UI) to load a remote file  
on demand.




The only unfortunate thing about function is they are not really
functions.


Ok, I will bite: what are they?


Another separable point to debate: resolved, classes should freely  
nest (in
other classes and functions) and generate new entities each time  
they are
evaluated. Just like functions (ignoring or removing the joined  
function

object option from ES3).


Great!


I phrased this as a proposition to debate pro or con. I didn't mean  
to say it was resolved (but I hope it will be, in Harmony).



There are deeper waters to do with types,


Yes. The parent-child windows issue both declaring the same or
different class Foo seems like an important detail. Perhaps provably
making nominal types useless or at least as awkward as instanceof?


No, nominal types have their uses. In two disjoint globals, loading  
code defining the same nominal type should result in two types, not  
one -- we don't want to trust the name, or compare the contents. The  
name would simply be qualified by some kind of global identifier or  
pathname.


Nominal type use-cases for security, which I've mentioned before,  
include auditors (http://www.erights.org/elang/kernel/auditors/) and  
hybrid information flow systems (http://www.ics.uci.edu/~franz/Site/ 
pubs-pdf/C46Prepub.pdf, see figure 3). When you need type relations  
and equivalence based on name bound by special form, it's hard to do  
without. As Mark pointed out in Oslo, nominal types plus lexical  
scope let human and machine auditors know *exactly* what  
implementation(s) a class has.


One can make nominal types via branding in a structural type system.  
There's more to say here, later.


/be

___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Es-discuss - several decimal discussions

2008-08-25 Thread Brendan Eich
On Aug 25, 2008, at 1:59 PM, Mark S. Miller wrote:

 On Mon, Aug 25, 2008 at 1:20 PM, Brendan Eich [EMAIL PROTECTED]  
 wrote:
 On Aug 25, 2008, at 6:45 AM, Mark S. Miller wrote:
 What is it you and Sam are agreeing about? I lost track.

 That if we make cohort members == and ===, telling anyone who  
 still wants to
 distinguish 1.0m from 1.00m to use compareTotal is good enough.

 I agree with this if-then, but why not recommend Object.identical  
 instead?

Cuz it's more work for 3.1 than needed, and compareTotal is required  
by P754 IIRC. Either's good, Object.identical is better, but when in  
doubt... Yeah, I'm still thinking in Decimal for ES3.1 terms here.


 In any case, is there any general agreement about *whether* 1.0m ==
 1.00m or 1.0m === 1.00m? This is where I lost track.

Yes, I believe Sam and I agree on those holding true. As you note,  
typeof x == typeof y  x == y = x === y, so anything else will  
break that relation, and it's not just an ideal form: users,  
especially those taught to avoid == in favor of ===, will have our  
heads if 1.0m != 1.00m.

/be

___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: local

2008-08-25 Thread Brendan Eich
On Aug 25, 2008, at 3:00 PM, Ingvar von Schoultz wrote:

 ...we'll have to write something like this?

  const
  {   DatabaseName,
  DisplayCount,
  ... Ten more ...
  } =
  Debugging ?
  {   DatabaseName: TestDatabase,
  DisplayCount: 5,
  ... Ten more ...
  }
  :
  {   DatabaseName: RealDatabase,
  DisplayCount: 15,
  ... Ten more ...
  };

 Very often conditionals aren't that simple. It'll get ugly. The
 new awkwardness does makes sense in big projects, but only there.

Another way of looking at this is to say that const should be write  
once, not necessarily initialized in the declaration. Then you could  
write

const DatabaseName, DisplayCount, /* ... ten more ... */;
if (Debugging) {
 DatabaseName = ...;
} else {
 etc.
}

This was ES4's const. At the Oslo meeting there was strong opposition  
to write-once. The reasons were not clear to me (could be my fault).

Here you show a reason for write-once. The alternatives are  
destructuring from a ternary (as you showed), falling back on var  
(losing), or inventing some super-const binding form that escapes its  
block (not in the cards).


 let
 blocks and let expressions do not have solid support in TC39.

 I have no opinion on whether let blocks and let expressions
 are useful, but you could make them very cheap by dropping the
 intricacies that make let(x=x){} refer to two different x'es:

  let (a = x) {...} desugars to {let a = x; ...}

If by cheap you mean easy to implement, there would be a savings to  
compiler costs, but not at runtime.

  let (a = x) a; desugars to {let a = x; a;}

Sorry, no: the latter is not an expression, the former is (if you  
remove the ; at the end).


 As a bonus everyone will rejoice at the lessened cognitive burden
 of intricacies.

But then why have the let block form at all, since let declarations  
are sweet enough.

The case for let expressions remains even if you eliminate the let  
binding rule, since they are expressions. You'd have to invent  
generalized BCPL- or Algol-68-like expression language support, which  
is also not in the cards (I mentioned the idea briefly in Oslo, more  
as a joke or an aside).


 Of course Schemers will find a let with these semantics confusing.
 Clearly it needs a different name. How about... local? :-D

Sorry, no; please stop nagging.

/be
___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: return when desugaring to closures

2008-08-25 Thread Brendan Eich
On Aug 25, 2008, at 4:10 PM, Mark S. Miller wrote:

 are shallow generators
 implementable by a local cps transform?

Yes, the local evaluation (inside the generator function) is the only  
place that needs to be CPS'ed to allow yield in any expression or  
statement context.


 This approach would seem relevant to adding generators by adding new
 semantic state. But would it help us understand how to add generators
 by a local code transformation?

Why does this matter? Changing any future ES spec to use CPS is a  
semantic state shift, and a very big one. The plan (designed and  
implemented by Dave) for specifying generators in ES4 was to use  
delimited continuations in the SML reference implementation.

It's not pretty, but you can CPS-convert generators. Here's a  
concrete desugaring (souring? :-P) example based on JS1.7, not  
ES4 (no iterator namespace, ugly __iterator__ name instead):

function simple_range(n) {
 for (let i = 0; i  n; i++)
 yield i;
}

function simple_range(n) {
 let i = 0;
 return {
 __iterator__: function () {
 return {
 next: function () {
 if (i == n)
 throw StopIteration;
 return i++;
 }
 }
 }
 };
}

Object.freeze on the returned iterator object omitted ;-). Adding  
send, throw, and close also left as an exercise.

/be
___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Consistent decimal semantics

2008-08-25 Thread Brendan Eich
On Aug 25, 2008, at 4:41 PM, Waldemar Horwat wrote:

 We're going round in circles on a few issues surrounding Decimal.

It seems to me people have reached the conclusion you already did on  
===. I'm not sure anyone advocated otherwise (I've missed most 3.1  
calls lately, so can't be sure).


   Some of these have clear resolutions; others have a little wiggle  
 room.  Here's my summary:

Thanks, the FAQ format is helpful. I agree with your answers, but I  
have a couple of questions.


 - Should decimal values behave as objects (pure library  
 implementation) or as primitives?

 If they behave as objects, then we'd get into situations such as  
 3m != 3m in some cases and 3m == 3m in other cases.  Also, -0m !=  
 0m would be necessary.  This is clearly unworkable.

What should be the result of (typeof 3m)?

[snip]


 - What should cross-type === do on 5 === 5m?

 These objects are of different types, so it should return false.

Confusion: 5 is of number type (a primitive type, typeof agrees),  
so These objects should have been These values -- right?

Sam and I, not going in circles (much), agree that typeof 3m should  
be object, and that we add hardwired operator support for such  
Decimal objects.


 - How should mixed type arithmetic work in general?

 There are a few consistent design alternatives:

 1.  Always disallow it.  For consistency you'd have to disallow ==  
 between Number and decimal as well.

This was what Igor Bukanov and I were advocating last week.


 2.  Allow it, converting to the wider type (Decimal128).  There are  
 a couple design choices when doing the conversion:
 2a.  Convert per the IEEE P754 spec:  5.1 turns into  
 5.099644728632119949907m.  This is how most programming  
 languages operate (C++, Java, Lisp, etc.) when converting among the  
 built-in floating point values (float - double etc.).

(I'm asking anyone who thinks so, as well as asking for your  
opinion:) Better than alternative 1? If so, why?


 2b.  Convert the Number to a string and then to a Decimal:  5.1  
 turns into 5.1m.  As a special case, -0 would turn into -0m.  This  
 might work, but I haven't thought through the implications of this  
 one.

Interesting idea.

/be
___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Look Ma, no this (was: ECMAScript Harmony)

2008-08-25 Thread Brendan Eich
On Aug 25, 2008, at 4:57 PM, Peter Michaux wrote:

 There needs to be a way(s) to distinguish which variables have which
 lifetimes and visibilities.

We have ways already: explicit blocks containing let-declared  
temporaries; your public to make things visible outside their lexical  
scope.

Rules to be worked out, I am going fast here (don't slow me down ;-),  
but I do not see the point in reinventing wheels or mixing them into  
hybrids.


 The following is no good

 class Foo() {

BTW, no need for () after the class name -- a bit more sugar.


   var temp = 0;
   var priv = 1;
   var pub  = 2;
 }

 It could be

 class Foo() {
   var temp = 0;
   private priv = 1;
   public  pub  = 2;
 }

 In the above example, temp will be garbage collected and there is no
 use in the private priv variable and it could be garbage collected
 too.

Why reinvent the wheel with private? Functions outside of classes  
do not capture any such declared bindings.

class Foo {
   var temp = makeBigObjectGraph();
   var nontemp = computeSomeResult(temp);
   var nontemp2 = computeAnotherResult(temp);

   function private_method() {...}
   public function public_method() {...}
}

This is bad. Without inventing more syntax, one way out is to write

class Foo {
   var nontemp, nontemp2;

   {
 let temp = makeBigObjectGraph();
 nontemp = computeSomeResult(temp);
 nontemp2 = computeAnotherResult(temp);
   }

   function private_method() {...}
   public function public_method() {...}
}

There are other ways around the unwanted entraining of the big object  
graph. You could ask for a constructor function inside the class, as  
AS3 and ES4 support. But it's still possible to entrain too much in  
such a function, and you can't initialize the member vars directly in  
their declarations (this combined with non-null types led to the  
settings syntax in ES4).

So really, caveat hacker. Closures can hang onto too much memory if  
you are not careful.


 The situation changes when a public method exists.

 class Foo() {
   var temp = 0;
   private priv = 1;
   public  pub  = function() temp + priv;
 }

 Now temp is captured in the closure of pub and so temp is
 effectively instance-private. So the private keyword isn't necessary
 at least in terms of lifetime as the following is the same.

 class Foo() {
   vartemp = 0;
   varpriv = 1;
   public pub  = function() temp + priv;
 }

 This last example, no private keyword,

(Whew.)


 works if instance-private is
 desired. If class-private is desired (I hope not! as I explained
 before) then the second to last example above would be required. In
 which case var works like Ruby's private (instance-private),
 private works like Ruby's protected (class-private)

This reminds me of an idea from Dave Herman and Sam Tobin-Hochstadt  
to add private syntax for generating Name objects bound to lexical  
names (after define-local-member-name in PLT Scheme):

   private var priv = 1;

Not exactly the same syntax as you sketched, but you could also  
separate name generation from use:

   private priv;
   var priv = 1;

and make other uses in the same lexical scope of the (impossible to  
forge as a string) Name object mapped to the 'priv' lexical name.

This could be used for class private, C++ friend, and other such  
use-cases.


 and public is like everyone's public.

:-)


 So the issue may not be choosing between instance-private *or*
 class-private.

That's what I was getting at in an earlier message with the generated  
Names for class, friend, etc. private.


 JavaScript will have instance-private thanks to
 closures. The question becomes is class-private also desirable, worth
 the extra keyword and complexity both to learn and to debug?

It's a good question.


 I think the ability to have two modules in one file means modules will
 need to name themselves. That is they will need to be declared with a
 name like

 module foo {
   // ...
 }

 or

 var foo = module {
   // ...
 };

 The importer could rename things but somehow the importer will have to
 use the name foo to at least start importing.

I will let Ibad^H^H^H^HIhab jump in here ;-).


 By cycles you mean module A using module B which uses module A? Late
 linking would required to allow cycles, correct?

Yes. Any early linking would mean no cycles allowed, leaving us with  
second-class modules of the PLT Scheme kind (PLT Scheme has a first- 
class module system too, called Units, which does allow cycles). At  
this point I should summon and defer to Dave Herman (who may be a bit  
too busy to respond, but here's hoping).


 Also perhaps the
 foo variable may reference different module objects at different
 times.

The var foo could be rebound, but modules by default should have  
higher integrity than that.

/be
___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: return when desugaring to closures

2008-08-25 Thread Brendan Eich
On Aug 25, 2008, at 6:15 PM, Mark S. Miller wrote:

 Thanks, that helps a lot. But shouldn't that i == n be !(i  n)
 since it's a transform of the original i  n?

Sure -- was going fast (other work competing ;-).


 On Thu, Aug 21, 2008 at 11:31 PM, Dave Herman [EMAIL PROTECTED]  
 wrote:
 Can't be done without defining the entire language in CPS. Yes, it's
 shallow, but a captured activation can involve any arbitrary  
 combination of
 expressions other than function call.

 Dave, is the violent transform of the for-loop above the kind of
 rest-of-the-language transform you were referring to?

Answering for Dave: yes.


 If so, isn't
 this only an issue for control structures (including , ||, and ?:)?
 What other elements of the language might need to be turned inside out
 this way? Or have I misunderstood what you're getting at.

As in Python 2.5, JS1.7 and up support yield expressions too. These  
return values and resume with new values when the generator is  
continued via next (which sends undefined) or send(v) (arbitrary v).  
The simple_range example I showed happened to use yield as an  
expression-statement.

I don't expect we'll CPS-transform any future ES spec, but you are  
entitled to pain if you like it ;-).

/be

___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Look Ma, no this (was: ECMAScript Harmony)

2008-08-25 Thread Brendan Eich
On Aug 25, 2008, at 7:07 PM, Erik Arvidsson wrote:

 I've been quiet on these threads for a long time but i just wanted  
 to emphasize Kris's point. Whatever we decide to desugar the class  
 syntax into I think it is very important to get this right. We need  
 to make classes work with existing prototype based inheritance  
 chains. I would consider it a failure if I cannot create a class  
 that inherits from dijit.TabPane or from a Prototype UI component  
 for that matter.

Can you define inherit more precisely? If it's a matter of giving  
classes .prototype objects, perhaps this could be done (it's  
attractive since the built-ins, Object, Date, etc., are classes as  
well as constructor functions, which have prototype objects).


 I would also like to know more about the arguments why people seem  
 to be set on a zero inheritance class model? Does that imply that  
 one can still achieve inheritance using prototypes or does it mean  
 that inheritance is not desired at all?

No, prototypes are here to stay. There's even Object.create to  
relieve prototypers from having to write constructor functions.

The desire to explore ZI is two-fold:

1. It may help the committee to see the smallest possible proposal,  
and work up from there to SI and MI.

2. It may help the language to avoid adding another kind of  
inheritance than prototype-based delegation.

/be

___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: return when desugaring to closures

2008-08-25 Thread Brendan Eich
On Aug 25, 2008, at 8:51 PM, Mark S. Miller wrote:

 How important is it that yield be an expression rather than a
 statement? It seems like a sibling of return and throw, so I don't
 think anyone coming to them afresh would be surprised if yield were a
 statement.

This is and was not a clean-slate exercise. We both followed and gave  
feedback to Python in doing this work, because the Python and JS  
communities overlap significantly, and the languages share certain  
stylistic and substantial features (not all, but enough). The goals  
include reusing the Python open-source/python-dev experience and the  
developer brainprint.

yield as an expression form is important for so-called co-routines,  
where you can call gen.send(val) to resume a generator the val  
becoming the result of the last yield expression; you can also  
gen.throw(exc).

Finally, and this is possibly the most useful, gen.close() will be  
called in JS when a generator used in a for-in construct. With close  
called from for-in, cleanup can be automated that otherwise can't be  
done without Python-style ref-counting/GC, Java-style finalization,  
or worse -- complexities we wish to avoid in any ES standard.

Calling gen.close() on an open generator forces a return from the  
last yield. This has the desirable property that if the yield is in a  
try, any relevant finally clauses will be run. (Return from generator  
throws StopIteration, as usual for iterators; a generator can't  
return a value.) Background reading:

http://mail.python.org/pipermail/python-dev/2006-August/068497.html
http://mail.python.org/pipermail/python-dev/2006-August/068498.html
http://mail.python.org/pipermail/python-dev/2006-August/068450.html

One use of generators, which Neil Mix wrote: Threads in JS:

http://www.neilmix.com/2007/02/07/threading-in-javascript-17/

Source to read:

http://www.neilmix.com/demos/js17threading/example.js
http://www.neilmix.com/demos/js17threading/Thread.js

These use send and yield expressions heavily. The es- 
[EMAIL PROTECTED] archives at

https://mail.mozilla.org/pipermail/es-discuss/

best searched with Google site:mail.mozilla.org search, have a number  
of threads tracing the evolution of generators. Besides Igor  
Bukanov's work to simplify the close mechanism by eliminating  
GeneratorExit, Chris Hansen of Google made the crucial proposal to  
automate close only from for-in constructs (not from GC).

Generators are in JS1.7 (Firefox 2). Sugar in the form of generator  
expressions, as in Python 2.4, are in JS1.8 (Firefox 3). My port of  
Peter Norvig's Sudoku solver, which uses genexps:

https://bugzilla.mozilla.org/attachment.cgi?id=266577

I believe Pythonic generators have been the most useful, if not most  
widely used, of the extensions that we have shipped since JS1.5 (ES3  
+ getters and setters).

/be
___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: dynamic class idiom

2008-08-26 Thread Brendan Eich
On Aug 26, 2008, at 2:49 PM, Dave Herman wrote:

 I noticed a little idiom supported by classes-as-values:

  (new (class() { ... }))

 This essentially builds an object whose properties can be computed  
 in an
 arbitrary statement context-- with loops or what have you. You might
 call this a dynamic singleton pattern; a throwaway factory. It's  
 not a
 global singleton like in Java; it's just an ordinary expression so it
 might be called by a function or whatever.

Probably everyone involved favors first-class classes -- first-class  
meaning classes as values (not only as named defining forms),  
nestable. I hoped so in reply to Peter yesterday.


 Worth a little sugar? E.g.:

  object { ... } ~=~ (new (class() { ... }))

Does not say class, seems to save only a few chars (you over- 
parenthesize new ;-). Wait for demand?


 or maybe to conserve keywords (a bit backwards-incompatible):

  new { ... } ~=~ (new (class() { ... }))

This is not incompatible at all, since an object initialiser has no  
[[Construct]] in ES3, so cannot be the operand of new.

/be

___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: dynamic class idiom

2008-08-26 Thread Brendan Eich
On Aug 26, 2008, at 4:16 PM, Dave Herman wrote:

 Does not say class, seems to save only a few chars (you
 over-parenthesize new ;-). Wait for demand?

 It's not about saving chars so much as introducing a new (lightweight)
 semantic concept: an object initializer that is a block rather than a
 table mapping names to expressions. Not saying `class' is the point.

But you'd say class if you needed to define the operand to new for  
other uses, or for some other reason motivating against this  
lightweight form. So the concept seems to have two names when  
generalized slightly.

Specializations can have special names, don't get me wrong. But  
object is way overloaded.


 I over-parenthesized because I wasn't sure how it would parse if you
 said e.g.

  new class() { ... }.foo

That should be unambiguous, and work as this does in ES1-3:

 new MyClass(arg).foo

The grammar goes to some lengths to group (new MyClass(arg)).


 or maybe to conserve keywords (a bit backwards-incompatible):

  new { ... } ~=~ (new (class() { ... }))

 This is not incompatible at all, since an object initialiser has no
 [[Construct]] in ES3, so cannot be the operand of new.

 Right, but that means that existing code isn't using this form, so you
 could steal this special case; then the argument to `new' would  
 have to
 be an expression that didn't start with '{', just like expression
 statements. It's backwards-incompatible but since the current syntax
 only leads to a useless error, I doubt real code is using it.

We consider such guaranteed errors to be unused, and call changes to  
claim the syntax backward-compatbile. At least we did in the ES4 WG.  
ES3 chapter 16 allows implementations to extend in this way, too.

/be

___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Proposal: opt-out local scoping

2008-08-28 Thread Brendan Eich
On Aug 28, 2008, at 12:14 PM, Dave Herman wrote:

 I interpreted Erik's point to be that the binding of `this' is not
 lexically scoped, so it would be useful to have a lexically scoped
 variable initially bound to the global object. IOW, if I write:

  this.print(blah blah blah)

 and then I refactor the code to say:

  (function() {
  this.print(blah blah blah)
  })()

 it breaks.

It happens not to break, because ES3 requires a null |this| for such  
calls, where the null is later replaced by the global object.

obj = {
 method: function () { this.print(blah blah blah); },
 print:  function () { print(not the print you want); }
};
obj.method();

would break, though.

We've been trying to fix the ES3 null-global rule for a while. Any  
change is an incompatible change, but the current rule leads to  
unintended global mutation and capture bugs.


 By contrast if I have a standard library binding `global'
 that's bound to the same thing as `this' at the top level, then I  
 can write:

  global.print(blah blah blah)

 and the same refactoring:

  (function() {
   global.print(blah blah blah)
  })()

 continues to work the same. But there's no need for a special  
 keyword or
 anything like that.

Indeed, Doug Crockford proposed at the January TC39 meeting this year  
to make 'this' act like a lexically bound variable, with the only  
magic to it applying to the case of obj.method() call expressions  
(and variatons, obj[name] where name = 'method'), where 'this' would  
be overridden -- if you will, a shadowing 'this' would be bound to obj.

I liked Doug's proposal quite a bit. I do not see anything like it in  
ES3.1, but I'd like to see it in Harmony.

/be
___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Proposal: opt-out local scoping

2008-08-28 Thread Brendan Eich
On Aug 28, 2008, at 1:23 PM, P T Withington wrote:

 I'd like to have a syntax where this is _not_ implicitly bound.  One
 idea would be to riff on default arguments:

function example (receiver=this, ...

Why wouldn't you use |this| for the parameter name? We did for type- 
annotating |this| in various proposals.

Some functions have a bound |this| when you extract them. Such  
override attempts would fail. Throw or fail silently?

/be

___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Proposal: opt-out local scoping

2008-08-28 Thread Brendan Eich
On Aug 28, 2008, at 2:59 PM, Ingvar von Schoultz wrote:

 Dave Herman wrote:
 Reformed `with' depended on type annotations and structural type  
 syntax,
 which are undergoing discussion. So I think reformed `with' is up  
 in the
 air for now.

 I find it odd that reformed |with| required such exact type
 annotations, when nothing else does.

Please read

http://wiki.ecmascript.org/doku.php?id=proposals:reformed_with

the last paragraph in particular.


 It would seem that these
 are very similar, from an early-binding viewpoint:

  var {a, b, c} = fn();
  x = a;

  var obj = fn();
  x = obj.a;
  with (obj : {a, b, c})
  {   x = a; // Desugars to obj.a
  }

Your example includes neither type constraints nor mutation.


 Equally it would seem that disambiguating syntax would allow
 early binding, if it were enforced:

  with (obj)
  {   x = .a; // Desugars to obj.a

New syntax could solve the ambiguity problem, but not the type  
variance problem.

/be

  y = a;  // From the lexical scope
  }

 -- 
 Ingvar von Schoultz

 ___
 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: Sugar unrelated to macros -- Was: Re: Sugar

2008-08-28 Thread Brendan Eich

On Aug 28, 2008, at 3:26 PM, Ingvar von Schoultz wrote:


Macros and functions are very, very different. My proposal
has only regular, run-of-the-mill functions. They don't have


do have, right?


parentheses around the arguments, but this detail doesn't
make them in any way related to macros and their problems.


If you mean hygiene, that is not a practical problem so much as a  
theoretical one. Dave knows a lot about this topic, so I'll defer to  
him.




I find it disconcerting that this list will so easily brush off
proposals with some vague comment about something never proposed.


Please cut the this list collective guilt assignment. Felix  
[EMAIL PROTECTED] replied identifying your idea with Python  
decorators, and you did not reply to him. Was his reply either  
disconcerting or a brush-off? No. Keep your arguments with  
individuals focused on individuals with whom you have a bone to pick,  
or better yet, avoid ad hominem (ad listinem ;-) arguments altogether.


/be



Ingvar



Ingvar von Schoultz wrote:

Dave Herman wrote:

The following would let people create syntax sugar for their
favorite paradigms.

I really have to suggest you learn about macros before trying to
reinvent them. This reading list is a good start:

http://library.readscheme.org/page3.html


The idea is to avoid the unsolved problems of macro hygiene.
That's why the arrangement has only function calls, no macros.


___
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: Sugar unrelated to macros -- Was: Re: Sugar

2008-08-28 Thread Brendan Eich
On Aug 28, 2008, at 5:35 PM, Dave Herman wrote:

 If you mean hygiene, that is not a practical problem so much as a
 theoretical one. Dave knows a lot about this topic, so I'll defer  
 to him.

 No, hygiene is most certainly a practical problem!

*Lack* of hygiene is a problem. My statement in reply to Ingvar's  
citing problems with macro systems was that, if he meant by  
problems anything like implementing hygienic macros, then  
building such systems is a solved problem for certain languages --  
albeit without complete formalization in theory. This is not to say  
hygiene being supported in Scheme transfers to JS, of course.

Ingvar's sugar proposal seems free of capture problems, at a glance,  
even if sugar definitions nest. But a more complete proposal would be  
needed to be sure. I was making a few assumptions from the examples.

/be
___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Strict undefined this

2008-08-30 Thread Brendan Eich
#c wins by maximizing TC purity, utility, and safety.

/be


___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Sugar

2008-09-03 Thread Brendan Eich
On Sep 3, 2008, at 3:11 PM, Peter Michaux wrote:

 On Wed, Sep 3, 2008 at 8:55 AM, Dave Herman [EMAIL PROTECTED]  
 wrote:

 As I've said, macros aren't on the agenda for this go 'round.

 Is there an official wiki location which states what the committee has
 agreed upon for Harmony?

Not yet. The agreements in Oslo were summarized in my ECMAScript  
Harmony post, and we've corresponded here since then about types,  
classes as sugar, etc.


 For example, if it is definitely known that
 macros and/or meta-programming is unanimously off the table by those
 with a vote then it would save a lot of energy.

Why not discuss these or other future topics if you have the  
interest? This is es-discuss, it's not targeted only at near-term  
discussions.

/be

___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Call for opinions: attribute defaults and renaming flexible

2008-09-03 Thread Brendan Eich
On Sep 3, 2008, at 10:51 PM, Mark S. Miller wrote:

 On Wed, Sep 3, 2008 at 9:49 PM, David-Sarah Hopwood
 [EMAIL PROTECTED] wrote:
 I don't see why any special case is needed here, or why removing it
 would require splitting [[Deletable]] from [[Configurable]].

 Suppose that [[Configurable]] = false prevents a writable data  
 property
 from being deleted or changed to non-writable. What compatibility  
 problem
 does this introduce? ES3 had no way for user code to change  
 attributes,
 so I don't see how there can be a compatibility problem.

 As I said in an earlier question from Ingvar  on the same issue:

 Legacy demands that new properties added to the global object by
 assignment or top-level declarations

Not by assignment -- only by var or function declaration not in eval  
code.


 start as non-deletable but
 writable. But runtimes for secure subsets of ES, like ADSafe and Caja,
 need to be able to freeze the global object of their frame during
 their initialization. If not for legacy, we could make new properties
 of the global object start as configurable.

Except that deoptimizes all high performance JS engines.


 If deletable and
 configurable were distinct, we could make new properties of the global
 object start as configurable but not deletable.

Saving perf but to what end? Does the Caja, etc. programming model  
require configurability before freezing for all global props, or a  
few, or one?


 However, adding
 another attribute to deal with this one problematic case seemed
 overkill. Allowing non-configurable properties to be made non-writable
 seems like the simplest adequate solution.

Not arguing, just recapitulating and asking for the Caja use-case.

/be

___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Es-discuss - several decimal discussions

2008-09-04 Thread Brendan Eich
On Sep 3, 2008, at 11:15 PM, David-Sarah Hopwood wrote:

 In the absence of decimal, Object.eq is trivial to spec:

Object.eq(NaN, NaN) = true
Object.eq(  0,  -0) = false
Object.eq( -0,   0) = false
Object.eq(  x,   y) = (x === y), otherwise.

 or to implement:

Object.eq = function (x, y) {
  if (x === y) {
return x !== 0 || 1/x === 1/y;
  } else {
return x !== x  y !== y;
  }
};

Even shorter, without else after return non-sequitur and with one  
guaranteed same-type == instead of === to be perverse:

Object.eq = function (x, y) {
 return (x === y) ? x !== 0 || 1/x == 1/y : x !== x  y !== y;
}

But what's the point?

My point was that Decimal doesn't make the case particularly strong,  
since you just need to add Decimal.compareTotal:

Object.eq = function (x, y) {
 if (x instanceof Decimal  y instanceof Decimal)
 return Decimal.compareTotal(x, y) == 0;
 return (x === y) ? x !== 0 || 1/x == 1/y : x !== x  y !== y;
}

How much less trivial is this? Two lines, fewer with more ?: chaining.


 Just not particularly on account of Decimal, even
 with equated cohort members.

 If there is a possibility that we are ever going to add decimal (or  
 other
 types for which === might not be an identity test), then adding  
 Object.eq
 now allows writing future-proof code for such things as memoizers --
 whatever the semantics of === for decimals (or between decimals and
 other numbers) turns out to be.

JS developers have to cope with downrev browsers. There's no  
imperative now (ES3.1) vs. next time, since they'll need  
something like the above as fallback for last time (ES3-based)  
browsers.

Again my point is to avoid mission creep in 3.1. I have no problem  
with identical and hashcode. If I'm wrong and they can be slipped in  
without any delay, filling inevitable latency in the current  
schedule, great.

I should get busy on the spec.

Ob. Bikeshed: You seem committed to eq as the name. I say it's undue  
Lisp nostalgia, if not arrant cybercrud. But I concede that identical  
is overlong. Alternative ideas?

/be

___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Es-discuss - several decimal discussions

2008-09-04 Thread Brendan Eich
On Sep 4, 2008, at 12:29 AM, David-Sarah Hopwood wrote:

 1. You can't do that in ES3.1 if Decimal is not in ES3.1. You'd have
 to add typeof Decimal !== 'undefined'  to the 'if' condition.
 And then you'd be trying to anticipate a future spec, rather than
 relying on an existing one.

Straw man -- Ajax library authors have to object-detect, they do it  
as needed. We can't predict the future, so why worry? The point is  
that Object.eq could be done now or later. There's no imperative to  
do it now, with or without Decimal. Whatever the mix of Decimal and  
Object.eq, library authors can and must cope -- since they'll face  
downrev browsers.


 2. This only accounts for Decimal, not for any other future types  
 where
 === might not be an identity comparison.

Accounting for the future is not a reason to add an API that can be  
self-hosted (and will be, for older browsers).


 3. It's not clear to me that this code is correct; at least not  
 without
 making assumptions about how === will work on mixed arguments that
 have not yet been agreed. Will 1 === 1m be true (when decimals are
 added)? If so, then Object.eq(1, 1m) as implemented above will be
 true when it should be false.

We haven't agreed on X, Y depends on X, therefore Y is not ready to  
spec -- yup, you're right. That doesn't mean we must add Object.eq  
now just to future-proof (even within the future that's before 3.1  
is done!). Cart Horse, ahead of.


 The size of the code is irrelevant. Object.eq doesn't add  
 significantly
 to language complexity, and provides a useful basic operation, so why
 shouldn't it be in the spec?

Are you familiar with requirements management, scheduling? It was not  
the last addition that made us late. It was not the last cookie I ate  
that made me fat.


 Unless they are targetting only ES3.1-and-above. At some point (maybe
 several years) in the future, they'll be able to do that --  
 provided that
 Object.eq was added in ES3.1.

Or we do it next time and use the self-hosted version in the mean time.

You are trying to construct an absolute argument on relative terms. I  
could do that to add a large number of good APIs to 3.1 but then we'd  
be done in 2011. But if we keep arguing, we'll miss the chance to fix  
what's wrong in the current draft spec, so I'm going to stop here --  
have the last word if you like.


 Not really, but eq has been used to refer to this operation for  
 decades
 in both the Lisp and capability communities. I can live with
 Object.identical, but I'll always think of it as 'eq'.

Ok.

/be

___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Call for opinions: attribute defaults and renaming flexible

2008-09-05 Thread Brendan Eich
On Sep 5, 2008, at 4:33 PM, Ingvar von Schoultz wrote:

 Ingvar von Schoultz skrev:
 Mark S. Miller skrev:
 On Fri, Sep 5, 2008 at 2:33 PM, Ingvar von Schoultz
 [EMAIL PROTECTED] wrote:
 and silent failures
 are often very expensive to debug.
 I don't understand. As currently proposed, Object.freeze always
 succeeds. What silent failure are you concerned about?

 If you set a property to non-configurable it means you don't
 want it reconfigured. If code is still allowed to change it
 from writable to non-writable, this is a silent failure of
 the guard against reconfiguring.

 Another silent failure, much more expensive, is when you try
 to write to non-writable properties. (And, apart from this,
 also the related similar problem with constant variables).

This goes back to ES1. In Netscape's original JS implementation, I  
reported an error which stopped the script on assignment to read-only  
properties (this from memory, I don't have source code for the old  
Mocha runtime). Without try/catch in ES1, this was viewed as too  
harsh by the TG1 group in TC39, leaving only silent-but-deadly  
failure to modify the lvalue (the result of the assignment expression  
is the unfiltered right-hand-side value, so you can't tell).

This was not revisited when exception handling was added in ES3 :-(.


 I would really like to know the reason for this strange problem
 with non-writable properties, and try to see if there's any way
 a better solution can be found than this seriously expensive
 language bug.

The proposed solution for ES3.1 and beyond is use strict.

/be

___
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-09 Thread Brendan Eich

On Sep 9, 2008, at 1:49 PM, Garrett Smith wrote:

On Tue, Sep 9, 2008 at 11:32 AM, Mark S. Miller  
[EMAIL PROTECTED] wrote:

Should strict 'arguments' be an array? I know we've over this before
and that strong reasons were presented why we couldn't do this.  
But on

the ES3.1 phone call this morning no one could remember or regenerate
those reasons. Anyone? Pointers to previous threads are a fine  
answer.


There was a narrow-cast thread among ES3.1 principals, I replied  
without enlarging it. Here's my last message in full, citing Allen's  
agreement:


I only now noticed that this mail spun off from a narrowcast mail  
from Pratap, but the topic (arguments' type) deserves a wider list.  
[EMAIL PROTECTED] is fine. May be that we are done with  
this thread, but if not (or if it comes back to life), it should  
not be too narrowly distributed. There's always the TC39 reflector  
for member-only stuff.


/be

On Aug 1, 2008, at 6:26 PM, Allen Wirfs-Brock wrote:
OK, I generally buy this, that arguments is an Object but its  
[[prototype]] is Array.prototype. What about the semantics of its  
length property and other array specific semantics defined in Array  
instances’ custom [[Put]] method ([[ThrowablePut]] in the ES3.1  
spec.). I would think--yes, which means we will need to define a  
custom [[ThrowablePut]] for argument objects.  That is probably  
also the appropriate place for defining the mapping to/from actual  
parameters semantics.


At least one thing in Array.prototype that doesn’t fit if arguments  
is an Object and not an Array.  That is the definition of  
constructor in Array.prototype. We can fix that by explicitly  
providing an over-riding constructor property on arguments  
instances.  Are there any other properties of Array.prototype that  
need special consideration?


Finally, this  brings to mind a subtlety to think about.  The  
Object meta functions can expose whether or not a property is an  
own property or an inherited property.  When the speciation says  
(as it does in several places) that an instance of  a specific  
constructor has certain properties are  we implying that those  
properties must be observably own properties of the instance?  From  
an implementation flexibility perspective I’d prefer that this was  
left unspecified but from an interoperability perspective I suppose  
we should pin it down.


From: Brendan Eich [mailto:[EMAIL PROTECTED]
Sent: Tuesday, July 29, 2008 7:34 AM
To: Pratap Lakshman (VJ#SDK)
Cc: [EMAIL PROTECTED]; Mark S. Miller; Kris Zyp; Mike Cowlishaw;  
Adam Peller; Sam Ruby; Lars Hansen; [EMAIL PROTECTED]; Allen Wirfs- 
Brock; Waldemar Horwat

Subject: Re: ES3.1 WG phone conference 29 July 08:00 PT

On Jul 29, 2008, at 7:04 AM, Pratap Lakshman (VJ#SDK) wrote:


(3) arguments. I think we should make arguments a true ES array. We  
should correct the specification error that allowed it to be  
anything else.


This is not possible without extra magic, due to the aliasing of  
arguments[0] and x in


function f(x){arguments[0] = 42; return x}

It goes both ways of course:

function f(x){x = 42; return arguments[0]}

You can't require analysis to find the mutation (of either alias),  
due to eval. We shouldn't require any kind of analysis in ES3.1 to  
handle this aliasing. It has to be done as it has always been done,  
by a magic arguments object whose element getters know how to find  
the actual parameters, and whose element setters update those  
actuals that correspond to declared formal parameters.


Note that the last sentence requires the first call to f below to  
return undefined, not 42:


js function f(a,b){arguments[1]=42;return b}
js f(1)
js f(1,2)
42

For these reasons, arguments cannot be a true array. Such a change  
is also not backward compatible in ways I recall Lars found out  
about when he was at Opera.


The only harmonized solution is to make arguments' prototype be  
Array.prototype. Let's please do that, or else leave arguments alone.



(4) Edits based on review feedback from Oslo; schedule for  
circulating the next draft


Sorry if I cannot attend this meeting -- I will try if my schedule  
permits. I'm still traveling and I haven't had a chance to dig into  
chapter 15 of the spec. I hope the above is clear.


/be




Back to the present:


Thanks.



There are other threads covering arguments, not hard to find with  
site:mail.mozilla.org or nabble.com (although both have odd gaps in  
message indexing -- I'll talk to mail.mozilla.org admins).




The arguments object could have the same methods as array, like a
subclass of array, but not have the special [[Put]], and concat()
could still work the way it does with today's arguments object (I
don't actually prefer the current behavior)


The plan has been to make arguments objects delegate to Array.prototype.

/be

___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Function.prototype.bind

2008-09-09 Thread Brendan Eich
On Sep 9, 2008, at 9:47 PM, David-Sarah Hopwood wrote:

 As an alternative to saying the original bindings of... in the spec,
 we could provide a way to actually get the original bindings in  
 ECMAScript
 code. This is independently useful, e.g. for secure subset run-times.

Have you read http://wiki.ecmascript.org/doku.php? 
id=strawman:lexical_scope yet?

The Harmony reference implementation work is very likely to cut back  
the old ES4 RI to ES3 and go forward from there. To avoid hijacking  
built-in behavior it needs something like the use lexical scope  
pragma.


 I have also assumed the existence of a static Function.apply which
 takes the function to be applied as an explicit first argument.

This was part of ES4 and it's in JS1.7+ in Firefox.

/be
___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Function.prototype.bind

2008-09-10 Thread Brendan Eich
On Sep 10, 2008, at 6:24 PM, David-Sarah Hopwood wrote:

 David-Sarah Hopwood wrote:
 Mark S. Miller wrote:
 On Wed, Sep 10, 2008 at 12:49 AM, Brendan Eich  
 [EMAIL PROTECTED] wrote:
 I'm willing to rename Function.apply, but let's talk some more  
 about the
 better name, and about why it matters.

 Actually now that I think about it, there is an easy fix:

   Function.apply = original Function.prototype.apply;

 Then use Function.apply.call(callable, thisobj, argsarray).

 I should have said that this is assuming the adoption of my other  
 proposal
 in which static methods of Function (for example) are non-Writable and
 non-Configurable.

Oh, I thought you were dodging the overwrite issue. But your proposal  
is wildly incompatible and no browser implementor involved in TC39  
will ship it (I predict, and aver on behalf of Mozilla, having tried  
once for all standard constructors).

So where does that leave us?

/be

___
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-12 Thread Brendan Eich
Great -- good to have library authors / maintainers on this list.

I hold no brief for callee. The only issue in its favor is the cost of  
migrating to strict mode. A new version of Prototype that loses  
internal arguments.callee uses and is otherwise compatible helps.

Dojo and other Ajax folks on the list, please pipe up.

/ be

Sent from my iPhone

On Sep 12, 2008, at 6:54 PM, Tobie Langel [EMAIL PROTECTED]  
wrote:


 On Sep 11, 2008, at 14:34 , Brendan Eich wrote:

 I snipped your words about callee, but it's used quite a bit in Ajax
 libraries, e.g, Prototype:

 $ grep -w callee prottype.js
 replacement = arguments.callee.prepareReplacement(replacement);
 var self = arguments.callee;
 parts.add = arguments.callee.addPair;

 (Prototype 1.5.1.1.)

 In Prototype, arguments.callee is used in two distinct cases:

 1) reading a property of the callee, and
 2) recursively calling the callee.

 Case #1 is easily solved by storing the said property in a closure,  
 or by setting it elsewhere (where it probably would be a better fit,  
 anyway).

 Case #2 is easily solved by using a named function instead. For the  
 particular case where it is used in Prototype, the anonymous  
 function lies inside of a closure, so there is no chance of  
 triggering the JScript scope bug nor of polluting the global  
 namespace when naming it.

 From what I understand, ES 3.1 strict mode compliance will be opt-in  
 and will require at least slight source code modifications (if only  
 to prepend it with the 'use strict'; expression). So current  
 versions of Prototype (or other libs, for that matter), will not be  
 ES 3.1 'strict' compliant by default.

 I'm not really worried about modifying Prototype to avoid use of the  
 arguments.callee property. As a matter of fact, we've already done  
 so in a development branch for Caja compliance.

 Note that jQuery does not use arguments.callee at all.

 Best,

 Tobie





___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Regexp capturing groups.

2008-09-15 Thread Brendan Eich
Good point -- could you please file a separate ticket and cite it  
here in reply? Thanks,

/be

On Sep 15, 2008, at 7:51 PM, Markus Jarderot wrote:

 Brendan Eich wrote:
 Steven did file

 http://bugs.ecmascript.org/ticket/376

 I'll champion fixing this, somehow, in Harmony. We should get
 Waldemar's opinion on it.

 /be

 #376 seems to only concern the issue of back-references to
 non-participating capture-groups.
 What I described was back-references to capture-groups within a
 repetition. As the algorithm in the ECMA-262v3 is currently  
 written, any
 captures from the last iteration should be discarded.
 #376 mentions it, but also says that this deserves a separate  
 ticket. I
 have not found any ticket on this specific issue.

 I have recently found that also Google Chrome keeps the captures  
 between
 iterations.

 URI: javascript:alert(/(?:(a)|(b))*/.exec(ababa))

 Firefox 3.0.1:
 ababa,a, -- no b

 Internet Explorer 7.0.5730.11 and Google Chrome 0.2.149.29:
 ababa,a,b -- b in the end

 --
 Markus Jarderot
 ___
 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: Ye olde arguments argument (was: Topic list - pending changes and issues for the ES3.1 spec)

2008-09-15 Thread Brendan Eich
On Sep 15, 2008, at 10:13 PM, Jorge Chamorro 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.

I've been there, done that. Long ago, when crazy Smalltalk-ish  
reflection of execution state was in vogue, SpiderMonkey grew magic  
reflective properties (ugly names, such as __caller__). The compiler  
would make functions enclosing such things always have an activation  
object (real implementations must optimize away activation objects  
for performance -- there's no other way).

Besides violating Tennent's Correspondence Principle, this was an  
evil mess to implement correctly (consider all the optimizations that  
had to be undone). It's not worth it, especially if you want just  
callee (use a named function expression, or bind an outer lexical  
name) or caller (stack inspection should be served by a carefully  
designed API on the side -- mirror reflection, not an API on  
activation objects).

I agree with Mark about callee. Just say no, if we can wean folks off  
of it.

Stack backtracing deserves a separate thread.

/be

___
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 Brendan Eich
On Sep 15, 2008, at 10:21 PM, Jon Zeppieri wrote:

 Don't even get me started on activation 'objects'...

Nor me.


 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.

May be too big a change for 3.1, on the agenda for Harmony.

As Dave Herman has argued, mapping scopes onto objects is a primal  
sin in the ES specs. Recasting where possible via lexical bindings,  
putting the global object, with, and eval into penalty boxes, both in  
real terms for programmers (e.g. use lexical scope), and in the  
spec by making the bad cases entail exceptional work, seems more than  
worth the trouble.

It's easy to keep hacking around with objects, maybe trying to  
freeze some bindings, but doing so is a temporary evil at best, or  
foolish child's-play at worst (if done out of some misguided uber- 
minimalism, to avoid reforming the spec language to use lexical scope  
normatively).

Guy Steele was editor during much of the ES1 period, and he helped  
greatly, but compatibility concerns and time-to-market prevented us  
from taking his advice on this point. I wish we had, though.

/be
___
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 Brendan Eich
On Sep 16, 2008, at 12:21 AM, liorean wrote:

 2008/9/16 William Edney [EMAIL PROTECTED]:
 Could I do an assignment of the handler? Sure, but syntactically
 suboptimal, IMHO.

 Once JScript has fixed the function name scope bug, you could use

 myElem.addEventListener(
 'click',
 function f(){
 doSomething();
 this.removeEventListener(
 'click',
 f,
 false);},
 false);

Or to work around the JScript bug:

 (function () {
 function f(){
 doSomething();
 this.removeEventListener('click', f, false);
 }
 myElem.addEventListener('click', f, false);
 })();

Lots of workarounds, none free, but still possibly tolerable or even  
not measurable in performance and memory costs.

In case anyone missed it,

http://wiki.ecmascript.org/doku.php?id=proposals:stack_inspection

Ignore the type parameter and annotations, to see the essential  
proposal.

/be
___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: use decimal

2008-09-17 Thread Brendan Eich

On Sep 17, 2008, at 10:13 PM, Mark S. Miller wrote:

On Wed, Sep 17, 2008 at 6:50 PM, Maciej Stachowiak [EMAIL PROTECTED]  
wrote:




I agree that typeof 1.5m == typeof 1.1m. However, I do not agree  
that 1.1m == 1.1. These should be !=, since they represent  
distinct real numbers.


It seems to me that Brendan said 1.1m != 1.1 and did not question  
this.


Brendan, please correct me if I misrepresent your argument.

I took Brendan to be saying that

1) If typeof 1.1m were 'number' then we'd be obligated to have 1.1m  
== 1.1.


2) We want 1.1m != 1.1.

3) Therefore, typeof 1.1m must not be 'number'.

I disagree with #1 and thus #3.


Here is what I wrote:


Without use decimal, typeof 1.1m must not be number to preserve
this same invariant [that a === b  =  typeof a == typeof b  a  
== b].

Otherwise (without use decimal) 1.5m == 1.5
but 1.1m != 1.1, so without making typeof 1.5m != typeof 1.1m, we
cannot have typeof 1.5m == number.



Please expand your syllogistic reasoning:

Major premise #1: a == b
Minor premise #1: typeof a == typeof b
Conclusion #1: a === b
(you can switch == and === above -- the implication goes both ways  
and choice of == or === for typeof a OP typeof b does not matter  
since typeof's result is of string type.)


Major premise #2: 1.5m == 1.5
Minor premise #2: typeof 1.5m == number (your position, IIUC)
Conclusion #2: 1.5m === 1.5
(by Conclusion #1 and ES1-3 (which define typeof 1.5 == number))

Counter-example: 1.1m != 1.1
but typeof 1.1m == typeof 1.1 in your proposal (again IIUC)

This is a for-all problem. If there exists some double value x such  
that, for the decimal form y spelled literally using the same digits  
but with an 'm' suffix, x != y, yet typeof x == typeof y, then typeof  
must depend on whether its operand value converts losslessly to  
decimal from double and double from decimal.


This is broken -- typeof should depend on type, not value.

Hence my position (Waldemar's too) that typeof 1.1m == typeof 1.5m   
typeof 1.1m == decimal.



However, with the introduction of decimal, we've got cohorts  
galore. 1.1m has a different operational behavior than 1.1000m, but  
we've agree they should be ===. With the introduction of decimal,  
=== no longer approximates a test of operational equivalence, and  
we still need such a test.


=== does approximate operational equivalence apart from significance.  
Right? (I'm asking because I could be wrong, not rhetorically!)



0/-0 != 0/0. Does it thus seem wrong that -0 === 0?

Well, yes, actually it does seem wrong to me, but we all accept  
that particular wrongness. This is just more of the same.


A lot more.

Two wrongs don't make a right.

One exception to the rule is better than two, or 2^53 or larger.

/be

___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: use decimal

2008-09-17 Thread Brendan Eich
On Sep 17, 2008, at 7:48 PM, Sam Ruby wrote:

 Anybody care to mark up what they would like to see the following  
 look like?

http://intertwingly.net/stories/2008/09/12/estest.html

Shipt it!

(Not in ES3.1, certainly in Firefox 3.1 if we can... :-)

/be

___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Decimal comparisons

2008-09-19 Thread Brendan Eich
On Sep 18, 2008, at 10:58 PM, Kris Zyp wrote:

 * Like Crock, I prefer that typeof 1m === 'number'. However, unlike
 Crock's
 and Brendan's agreement, I think this should be unconditional. I  
 think it
 would be horrible for 'typeof X' to depend not only on the value  
 of X but
 also on the mode of the program unit in which the typeof appears.  
 Please
 don't do that.

 +1 for typeof 1m === 'number'. As an example of breakage, I believe
 Crockford's current version of his JSON library would not do as I  
 would
 desire with decimals:

 JSON.stringify({foo:1m}) - {\foo\:undefined}

Why is that worse than producing '{foo:1}'? Consider 1.1m instead  
of 1m.

JSON does not provide for decimal, and receiver-makes-it-wrong is a  
bug. JSON would need to be extended to handle decimal reliably.


 I think there is a may be a lot of code that is dependent on typeof
 returning a one of exactly six possible values.

There may be a lot. There's probably some. But there's also  
probably some code that breaks if decimals are added and they have  
number typeof-type. There is no non-breaking way to add decimal.

/be
___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Decimal comparisons

2008-09-19 Thread Brendan Eich
On Sep 19, 2008, at 8:45 AM, Sam Ruby wrote:

 The motivation for the fourth choice on the first question is to
 produce a value that is is valid JSON, is unlikely to be widely used
 today (by virtue of the capital E), will fall back to binary 64 many
 JSON implementations, and can be used as a signal to produce a decimal
 value in ECMAScript.  I'm merely putting this forward as brainstorming
 at this point, I'm less than enthusiastic about it myself.

http://www.ietf.org/rfc/rfc4627.txt underspecifies enough to allow  
this kind of trick, but it is possible that the de-facto JSON  
standard requires IEEE double at the limit.


 Does the committee feel that it can ever add new values to typeof
 under any circumstances?

Certainly not if there is opt-in version selection.

Even with the default version, people on this list have argued that  
adding a new typeof-type does the least harm and probably could be  
pulled off, because most typeof-using code does not test type-code  
values exhaustively. But it's an open question.


 FWIW, my preference is (in order): decimal, object, then number.

I'm with you there. The neo-Platonist camp (:-P) argues for number  
based on Real numbers, but machines and ES numbers do not behave like  
Reals. I don't believe object is thinkable without !0m = false, or  
widely distributed code will fail on decimal values.


 I think it is preposterous to assume that ECMAScript can never add any
 new data types.

Agreed.


 The version of JSON that is included in the language
 will be aware of the data types supported in that edition of
 ECMAScript.  What json2.js does for decimal, it does for any object
 data type that it doesn't understand.

This is not so clear. JSON is a cross-language, inter-networked data  
standard. It won't be easy to grow in parallel to ES standards. It  
shouldn't grow without versioning, which I'm sure Doug agrees should  
be avoided at all costs.

The risk for JSON is that because it underspecifies, real-world uses  
bind to specific implementations details such as number being double.


 As far as what the builtin JSON functionality slated for ECMAScript
 3.1 does when parsing [1.1], a case could be made that producing
 [1.1m] is the closest to the expressing what the data structure
 actually conveys, is readily convertible to binary 64 floating point
 when needed, and typical JSON isn't anywhere near as performance
 critical as vector graphic intensive functions are.

Yeah, you're right that this case could be made from the RFC,  
although the RFC talks only about range restrictions, not radix or  
rounding. But from an interoperating JSON peer today, you might find  
failures to round-trip. That seems bad.

/be
___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Regexp capturing groups.

2008-09-22 Thread Brendan Eich
On Sep 22, 2008, at 4:17 PM, Waldemar Horwat wrote:

 Brendan Eich wrote:
 On Sep 22, 2008, at 3:32 PM, Waldemar Horwat wrote:

 Brendan Eich wrote:
 Good point -- could you please file a separate ticket and cite it
 here in reply? Thanks,

 I filed a ticket to fix this bug in Chrome.

 The ticket I was asking for, which Markus is going to file now  
 that he
 has access to the http://bugs.ecmascript.org/ trac, is against  
 ECMA-262.

 Are you asking for Chrome (V8, I mean) to deviate from ES3 in  
 order to
 find out what breaks? If so, great, but how about coordination among
 Mozilla, Chrome, and WebKit (SFX)?

 /be

 No; it's the opposite.  I'm asking Chrome to conform to ES3.

Could you cite the chromium issue link? I'd like to learn what, if  
any, web compatibility knowledge was gained in in this case, or could  
still be gained.

/be

___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ES3.1 Draft: 22 Sep 2008 Redmond version available

2008-09-23 Thread Brendan Eich
On Sep 23, 2008, at 1:45 PM, Waldemar Horwat wrote:

 Sam Ruby wrote:
 One minor request: statements like breaks arrays are less helpful
 than specific ECMAScript statements which would fail; better yet  
 would
 be citing specific deployed code that would fail.

 I already gave specific examples of this and we've had extensive  
 discussions of them.  I don't like beating a dead horse any more  
 than necessary.


The horse must not be dead. The question is: should a === b imply o 
[a] and o[b] refer to the same property, for any object o (modulo the  
spec bug that David Jones pointed out whereby 5e-324 could be  
converted to strings such as 3e-324 and 7e-324).

Sam seems to think a === b should not imply o[a] and o[b] refer to  
the same property (double-cited text is from Jason Orendorff):

  Well, the intuition is that two equal numbers should index the same
  property.  This is an invariant in ES3 and it makes a lot of sense.

 Correct me if I'm wrong, but the intuition would more properly be  
 based
 on string equality, and not numeric equality.  As an example, how many
 properties would the following produce, with an conformant
 implementation of ES3?

 var a = [];
 a['0.0'] = first;
 a[0.0] = second;  // a second property
 a['0'] = third;   // replaces *second* property

The intuition depends on string equality and ToString in addition to  
numeric equality. But it turns out that a === b for any numbers a and  
b implies ToString(a) === ToString(b) (except, again, for the very  
small numbers David Jones pointed out).

But Sam's decimal implementation has 1.1m === 1.10m.

So the precise issue with breaks arrays is the proposal from Sam  
and Mike that ToString on a decimal preserve scale digits (I hope I'm  
using the right term). That breaks the a === b = o[a] is o[b] rule  
that exists today (modulo tiny values) for numbers a and b, when  
extended to decimals a and b.


 Intuition is a very tricky thing.  Place the following in front of any
 third grader, and tell me what they will write below the line.


 1 . 0 5
   + 2 . 0 5
   _


Of course the result should be 3.10 on paper, but this does not say  
that ToString applied to decimal must preserve scale digits.

One alternative is to distinguish the operation used when computing a  
property name from the ToString used everywhere else, and make the  
former lose scale digits while the latter preserves them. There's no  
doubt a 754r method for converting to string without trailing zeroes  
or otherwise preserving scale (those funny exponents Waldemar decried).

If we did this, we would have to complicate the spec by adding a  
special case to its computed property name logic. And users wishing  
to mimick it with explicit conversion to a string would not be able  
to use String(d) or  + d -- they would have to call the other method.

/be
___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ES Decimal status

2008-09-24 Thread Brendan Eich
On Sep 24, 2008, at 9:01 AM, Mike Cowlishaw wrote:

 I'm not sure what you are getting at. a[1] and a[1.000] refer to the
 same property in ECMAScript, but a[1m] and a[1.000m] would not. Are
 you saying this isn't a problem?

 Absolutely not a problem ... many languages (and ES itself) which  
 index
 'arrays' by strings treat the index 1.000 as different from 1, and
 this is not considered a problem.

But they do not treat 1.000 as an index differently from 1. Explicit  
string indexes, whether literally expressed or computed, are not the  
issue here.


 This is, no doubt, because if one is treating array indexes as a  
 set of
 integers you use integer operations on those indexes (almost  
 exclusively
 +, -, and *).  If one does use a divide,

Maciej pointed out reciprocal multiplication as strength-reduced  
division; this is done often enough in graphics and other low-level  
code.


 it would be carefully chosen to
 produce an integer result;

But what if scale is preserved?


 anything which produced a result without an
 exponent of 0 would always be more likely to give a non-zero  
 fraction that
 .0, .00, .000, etc. -- and those non-zero ones would fail rapidly.

Sorry, I didn't follow this (that should be than?).

/be



___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: ES Decimal status

2008-09-24 Thread Brendan Eich

On Sep 24, 2008, at 9:18 AM, Sam Ruby wrote:


[over-top-citing trimmed]
The concern remains, though. Not due to power-of-five problems that
would lead to 0.09987 or the like, but from cases where a
number was spelled with extra trailing zeros (in external data,  
e.g. a

spreadsheet) but fits in an integer, or otherwise can be expressed
exactly using powers of two. The burden of proof here is on the
invariant breaker :-/.


I fully appreciate the need for a high bar here.


Sure, so maybe that bar height is why people talk about broken.  
It's a presumption of guilt, alien to Anglo-Saxon jurisprudence.  
The Napoleonic ECMAScript code prevails here. Beware! :-P.



The problem here is that there are two invariants.  === to a high  
degree
of accuracy today is an eq operator.  But people have argued  
against 1.2

!== 1.20, because of another invariant:

a == b  typeof(a) === typeof(b) implies a === b

We can't satisfy both.


I do not think === is eq -- it's hard to argue degree when kind is  
the issue, as others have pointed out. Any hashcode addition would  
want eq, or force people to invent it at tedious and ineffecient length.


Past posts here have mixed up cohort and -0 vs. 0, but we've been  
educated thanks to MFC. Really, === breaks down on NaN and the  
zeroes, and there's no way to rationalize it as eq. I noted how Guy  
Steele helped us get past one broken equality operator, in order to  
add === and !== in ES1, and we talked about eq then. It still looms  
in the future, Harmony or (some argue) 3.1.




 My initial preference was that 1.2 !== 1.20, but
as we are not aware of code that uses fractional indexes, but are  
aware

of code that does generic typeof and equality testing, I would think
that the latter would have a higher weight.


Ignoring === as faux eq, the only issue here is d.toString() for  
decimal d: should it preserve scale and stringify trailing zeroes and  
funny exponents?


/be




/be


- Sam Ruby


___
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: Arguments and formal parameters aliasing

2008-09-27 Thread Brendan Eich
On Sep 27, 2008, at 8:14 PM, David-Sarah Hopwood wrote:

 liorean wrote:
 [...]
 10.1.3 Variable Instantiation
 [...] If two or more formal parameters share the same
 name, hence the same property, the corresponding property is given  
 the
 value that was supplied for the last parameter with this name.

 Can anyone explain what the original rationale was for this? To me it
 seems like duplicate parameter names are an obvious programming  
 error, and
 it makes no sense from a language design point of view to allow them.

I do not know. Shon Katzenberger of Microsoft may be the only person  
who can say. Duplicate formals were not allowed in my original (Mocha)  
Netscape 2-3 and rewritten (SpiderMonkey) Netscape 4-era  
implementations. JScript allowed them and the standard included them  
as a compromise (there were compromises in the other direction).


 (Yes, I understand that they are disallowed in ES3.1 strict mode,  
 and that
 disallowing them in non-strict mode would break compatibility. I'm  
 just
 curious what was going through the minds of the ES1 standardizers.)

The rationale is lost to the mists of time. I vaguely recall some  
belief that looseness in other parts of the language justified  
allowing duplicate formals, but bad doesn't justify worse. The  
complexity involved in supporting duplicate formals (compiling and  
decompiling) is out of proportion to any subjective value in the  
feature. Really, it's just a botch hammered out during ES1  
standardization based on JScript. There were botches on the JavaScript  
(Netscape) side too, so I'm not throwing stones.

Anyway, soon we can just use strict and move on. :-)

/be

___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: return when desugaring to closures

2008-10-09 Thread Brendan Eich
On Sep 2, 2008, at 2:16 PM, Lex Spoon wrote:

 On Sun, Aug 24, 2008 at 3:17 AM, Brendan Eich [EMAIL PROTECTED]  
 wrote:
 First, let's settle the hash over whether any desugaring without
 extensions such as return-to-label, reformed lexical scope, tamed
 this, banished arguments, etc. etc., trumps adding a new binding
 form, to wit: let as block scoped var.

 With no extensions, it is true, return would end up returning from a
 different method under the proposed rewrite.  Likewise, this and
 arguments would cause trouble.

Sorry for the very tardy reply. You make good points in the abstract,  
and the messy language-specific details of existing semantics for  
functions not being clean enough deserves a better response than just  
don't desugar.

I stand by don't desugar let to functions as-is. I'm also pretty  
certain don't add more modes or subsets to try to fix existing forms  
is sound, since versionitis does not  help us either keep the spec  
simple or specify the backward-compatible semantics in the full  
language.

So, to avoid trouble, we've been thinking of new forms including a  
better function, call it lambda, that has none of the compatibility  
baggage. I say we but really Dave Herman deserves credit for  
championing this. A lambda form has been a topic now and then for a  
while, on this list and in committee, and sometimes only as syntactic  
sugar (which would miss the opportunity for semantic reform) -- yet  
without it getting the breathing room it needs.

Dave is working now in the

http://wiki.ecmascript.org/doku.php?id=strawman:strawman

space on the wiki. Don't throw stones, this is not in the harmony:  
namespace for good reason. Constructive comments welcome. And I still  
owe the list a story on wiki access that keeps Ecma happy and doesn't  
throw open the edit wars doors.

Among the new strawman pages, the following are relevant and (I hope)  
helpful:

http://wiki.ecmascript.org/doku.php?id=strawman:lambdas
http://wiki.ecmascript.org/doku.php?id=strawman:lexical_scope
http://wiki.ecmascript.org/doku.php?id=strawman:return_to_label

 Possibly break and continue would,
 depending on what their precise semantics are.

JS has break from labeled statement, and continue to labeled loop  
bottom, a la Java. These look trouble-free to me. Let me know if you  
see a hard case. Thanks,

/be
___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: return when desugaring to closures

2008-10-09 Thread Brendan Eich
On Oct 9, 2008, at 3:05 PM, Lex Spoon wrote:

 On Thu, Oct 9, 2008 at 5:31 PM, Brendan Eich [EMAIL PROTECTED]  
 wrote: JS has break from labeled statement, and continue to labeled  
 loop bottom, a la Java. These look trouble-free to me. Let me know  
 if you see a hard case. Thanks,

 My question was whether the semantics of break and continue would  
 support the following:

 while(true) {
   (function() {
 if (--x == 0) break;
   })();
 }

That's currently a specified error (possibly at runtime; chapter 16 of  
ES3 allows it to be at compile time).

So a future edition could allow it, probably without opt-in  
versioning. Our compatibility model does not guarantee exceptions,  
since it allows contemporaneous extensions that remove those  
exceptions (see ES3 chapter 16 again, second bulleted list, first  
bullet -- these lists need their own sub-sections and numbers!).


 I honestly don't know, but it shouldn't cause any real trouble to  
 allow it.  The implementation would be analogous to that for labeled  
 return.

Right, and break to label outside the function's body, but lexically  
in scope, would be completely analogous (or just the same ;-)):

L: while (true) {
   (function () {
 ... // stuff possibly including a loop or switch that brackets  
the next line
 if (--x == 0) break L;
 ...
   })();
}

 For example, if the appropriate while loop is no longer on the  
 stack, the break would turn into an exception.

Yes, this new runtime exception is the price of admission.

The exception seems to a major source of grief in the Java BGGA  
closures controversy, or at least it did when I last looked. But it  
comes up with escape continuations in Scheme, and it is inevitable if  
we want these kinds of program equivalences.

I'm interested in the reactions of others on the list to such return/ 
break/continue from already-deactivated statement/frame exceptions.  
They could be caught and handled, of course. Feature and bug, dessert  
topping and floor wax ;-).

/be
___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: return when desugaring to closures

2008-10-09 Thread Brendan Eich
On Oct 9, 2008, at 4:28 PM, David Herman wrote:

 How would people feel about the declaration form being 'define'  
 instead of lambda? As in:

define const(x) {
lambda(y) x
}

 Maybe I'm just accustomed to Scheme, but it looks awkward to me for  
 the declaration form to be called lambda. Dylan also used 'define'.

For named functions, it's less cryptic, it has clearer connotations.  
For anonymous functions, e.g.:

   (define (x) {...})(x)

or

   return foo(define (y) {...}, z);

your mileage *will* vary, but it seems worse by a hair to me. But I'm  
used to lambda as a term of art.

The obscurity of lambda helps it avoid collisions (we have ways of  
unreserving keywords in property-name contexts, but these do not work  
for formal parameters and variables named define, which seem  
likelier at a guess than lambda -- spidering the web could help  
confirm this guess).

The obscurity also arguably partners lambda better with function.  
Setting up define as a cleaner function seems to switch domains of  
discourse. Concretely, we have in ES3.1 Object.defineProperty and  
similarly named functions. These define APIs were prefigured by  
Object.prototype._defineGetter__, etc.. This sense of define has  
meant bind property name to value or getter/setter.

On the other side, Python, E, etc. use def. But we would be verbose  
like Scheme and Dylan. So define vs. lambda.

End of my bike-shedding ruminations.

/be
___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: return when desugaring to closures

2008-10-09 Thread Brendan Eich
On Oct 9, 2008, at 6:44 PM, David Herman wrote:

 Sorry, I was unclear.

No, my fault for missing declaration form.


 I meant 'lambda' for the expression form and 'define' for the  
 definition form.

Do keywords cost more than concepts?

If people think define name(x) x and lambda (x) x are different  
beasts, then different names win.

If people think of lambdas (what else to call them? not functions)  
as being named or not when used as expressions, and named when  
declarations (parallel to the existing function forms are in ES3), but  
being different (albeit similar; cleaned-up) function-like beasts,  
then one name for the three forms that parallel the ES3 function forms  
seems better.

It's hard to argue about from first principles outside of the  
specifics of ES3 and modern JS implementations and teaching. The  
specific JS books I know talk about functions having several forms, so  
it seems better to me to keep lambda parallel. I see the appeal of  
define for the declaration (definition, rather) form, though.

/be

___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: return when desugaring to closures

2008-10-10 Thread Brendan Eich
On Oct 9, 2008, at 8:57 PM, Peter Michaux wrote:

 This keyword/scoping problem must already have appeared for functions
 as function declarations have var scoping and obtaining let
 scoping requires using something like let a = function(){}. This is
 pretty ugly for functions to have let scoping

An agreement from TC39 this past sprint was that function definitions  
directly nested in blocks, not specified by ES3, defined block-local  
(let) bindings.

There was general aversion to 'let function f() ...', an earlier ES4  
idea already on the ropes. Separating binding forms from function  
definition and other options (such as const) avoids too many binding  
forms ('let const', 'let function', etc.). But too many binding forms  
is just too many, and the committee strongly favored using grammatical  
placement to avoid adding more syntactic complexity.


 but the good news is
 the door has been left open for real lambdas to snatch up the
 available var a(){} and let a(){} syntaxes.

There's no reason to add var a() {} given function a() {} as a direct  
child of a program or function body. It seems to me let a(){} is  
Dave's define. So we're back to function vs. define/lambda.

The idea of a desugaring let statement and let expression require  
lambda, the reformed function (whether define wins or not). But let  
declarations as the new var do not desugar to lambdas. They hoist,  
even if forward references (use before set) are errors.

We haven't found a reformed var; I don't think there is one. This does  
not mean let declarations are somehow not worth adding. They're a big  
improvement on var declarations in our experience with let in JS1.7  
and up.

/be

___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Revenge of the double-curly [Was: return when desugaring to closures]

2008-10-10 Thread Brendan Eich
On Oct 10, 2008, at 5:44 AM, P T Withington wrote:

 On 2008-10-10, at 02:29EDT, Brendan Eich wrote:

 An agreement from TC39 this past spring was that function definitions
 directly nested in blocks, not specified by ES3, defined block-local
 (let) bindings.

 Holy smokes.  Does that mean we are all going to be writing

   function ... () {{
 ...
   }}

 to get 'normal' scoping of function body declarations???

No. My words were unclear, sorry. I wrote defined block-local (let)  
bindings meaning the functions defined in blocks bound *their own  
names* only in the containing  block, not in the variable object.


  Will `var`
 mean `let` in those double-curly bodies?

No, var and let mean the same thing at top level.

/be
___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Revenge of the double-curly [Was: return when desugaring to closures]

2008-10-10 Thread Brendan Eich
On Oct 10, 2008, at 11:58 AM, P T Withington wrote:

 ?  If so, perhaps you can see how I might imagine that:

   function foo () {{
 var bar = ...;
   }}

 might be sugar for:

   function foo () {
 let bar = ...;
   }

Nope, not compatible and not what I meant.

Just the function's name is let-bound (block-scoped) for a function  
defined directly in a block.

/be
___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: return when desugaring to closures

2008-10-10 Thread Brendan Eich
On Oct 10, 2008, at 1:25 PM, Waldemar Horwat wrote:

 So what should f(5, 0) do?

 function f(x, h) {
  while (true) {
try {
  if (h == 0)
h = function() {break};

Just to repeat something Dave wrote, we don't propose to allow break  
in a function where the break is not in a labeled statement, switch,  
or loop within that function. Only lambda would support such novelties.



  if (x != 0)
f(x-1, h);
  else
h();

This will break from the while (true) in the outermost (x = 5)  
activation of f.

In Scheme implementations that support it, the analogue is call/ec --  
call-with-escape-continuation (weak continuation is another name for  
escape continuation) -- where the caller's continuation is the  
argument to the procedure passed to call/ec. Escape continuations are  
cheaper to implement and simpler to reason about than full call/cc  
continuations because of the dynamic error (exception) you get if you  
call the escape continuation outside of the dynamic extent of the  
current call.

Sorry if this is already known; Dave should wipe my chin as needed  
since he is the adult Schemer here and I'm the toddler.


} catch (e) {
  alert(caught  + e +  on  + x);
} finally {
  alert(f called finally on  + x);
}
alert(f looping on  + x);
  }
  alert(f exited on  + x);
 }

The break itself does not propagate as an exception, just to be clear.  
If the statement being broken from is inactive, then an exception will  
be thrown from the break evaluation in the function that was assigned  
to h. The call to h would have to come after control flow had left the  
outermost while (true), via a statement after that loop, or some other  
call made via a returned or heap reference (upward funarg).

/be
___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: return when desugaring to closures

2008-10-10 Thread Brendan Eich
On Oct 10, 2008, at 3:31 PM, Brendan Eich wrote:

   } catch (e) {
 alert(caught  + e +  on  + x);
   } finally {
 alert(f called finally on  + x);
   }


Skipping the intervening active finally clauses is bad, though -- a  
bug in the current wiki rough draft that I should have mentioned. Dave  
will post a follow-up soon.

/be
___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Revenge of the double-curly [Was: return when desugaring to closures]

2008-10-11 Thread Brendan Eich
On Oct 11, 2008, at 7:25 AM, David-Sarah Hopwood wrote:

 It is correct to say, though, that:

  function foo() {
...
{ var bar = baz; }
...
  }

 is equivalent to

  function foo() {
let bar = undefined;
...
{ bar = baz; }
...
  }

 That is, 'var' need not be primitive. Only 'let' needs to be  
 primitive.

Indeed.


 Similarly, if we are careful in specifying 'lambda' then 'function'  
 need
 not be primitive, since it will be expressible as a rewrite to  
 'lambda'.

Yes, this is called out already in

http://wiki.ecmascript.org/doku.php?id=strawman:lambdas

/be


___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: return when desugaring to closures

2008-10-11 Thread Brendan Eich
On Oct 11, 2008, at 12:55 PM, David Herman wrote:

 How to define a variable that is local to the enclosing lambda? Isn't
 the ability to do that essential?

 No. With all due respect to Brendan, `var' hoisting to the top of a  
 function body is one of the more problematic aspects of ES's  
 semantics.

I agree, it's no skin off my nose -- 'var' hoisting was an artifact of  
function implementation in Netscape 2, and did not apply to global  
vars then. It was standardized as hoisting in all kinds of code  
(global, function, and eval). We are stuck with it. However, hoisting  
still applies to let:


 If you want a local variable, use `let' -- it'll be local to its  
 containing block. If you want a variable that is local to the entire  
 body of a `lambda', use `let' at the top level of the `lambda' body.

While let is local to containing block, the let-as-new-var proposal  
(implemented in Firefox 2 and up) hoists to top of block. So you  
cannot initialize the inner x using the outer x's value:

   {
 let x = 42;
 {
   let x = x; // undefined, not 42.
   alert(x);
 }
 alert(x); // 42, of course
   }

We've discussed making use-before-set a strict error, but we've  
avoided it. The initialiser is not mandatory, and we do not wish to  
impose costly analysis on small implementations.

/be
___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: return when desugaring to closures

2008-10-11 Thread Brendan Eich

On Oct 11, 2008, at 12:52 PM, Peter Michaux wrote:

On Sat, Oct 11, 2008 at 11:59 AM, Brendan Eich [EMAIL PROTECTED]  
wrote:

On Oct 11, 2008, at 9:05 AM, Peter Michaux wrote:

How to define a variable that is local to the enclosing lambda?  
Isn't

the ability to do that essential?


Use let (the var replacement declaration form).


Sounds good to me but it is a little confusing to keep track if let
is either in or out of ES-Harmony


I do not see why you are confused. I wrote, in the original  
ECMAScript Harmony post:


 I heard good agreement on low-hanging de-facto standard fruit,
 particularly let as the new var, to match block-scoped const as still
 proposed (IIRC) in 3.1.

See https://mail.mozilla.org/pipermail/es-discuss/2008-August/006837.html 
.




and if it is partly in then which of
the several JavaScript 1.7 uses are in and if there will be let,
let*, letrec semantics.


It's something else. See my reply about hoisting, just sent.

/be

___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: return when desugaring to closures

2008-10-11 Thread Brendan Eich
On Oct 11, 2008, at 2:43 PM, Brendan Eich wrote:

 On Oct 11, 2008, at 12:52 PM, Peter Michaux wrote:

 and if it is partly in then which of

 the several JavaScript 1.7 uses are in and if there will be let,
 let*, letrec semantics.

 It's something else. See my reply about hoisting, just sent.

Mark and others have described the let declaration (let as new var) as  
like letrec. Close, but since forward references are possible and  
initiialization in the declaration is not mandatory, it's analogous,  
not identical. The function definition form in JS is letrec. But let  
as new var? I still say it's something else; I admit that like  
letrec or letrec-ilke works.

/be
___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: return when desugaring to closures

2008-10-11 Thread Brendan Eich
On Oct 11, 2008, at 2:55 PM, Mark S. Miller wrote:

 On Sat, Oct 11, 2008 at 2:42 PM, Brendan Eich [EMAIL PROTECTED]  
 wrote:
 We've discussed making use-before-set a strict error, but we've
 avoided it. The initialiser is not mandatory, and we do not wish to
 impose costly analysis on small implementations.

 Since const use-before-set is an unconditional error (i.e., not
 dependent on strictness), implementations already have to pay for a
 read-barrier mechanism. Since we'd like to support
 type-annotation-constraints on initialized let variables, I think
 initialized let variables should have an unconditional read barrier as
 well.

If using an uninitialized let binding is an error, then hoisting is  
pointless except to make the statements between start of block and the  
let declaration a dead zone for the binding name. This fits the  
ancient, weak but not entirely worthless post-hoc rationale for var  
hoisting (to avoid confusion among novice or inexperienced programmers  
by making many scopes, each implicitly opened by var), but it's not  
particularly useful.

What's more, as discussed here and in TC39, repeated let declarations  
for the same binding name within the same block should be allowed.  
Anything else is user- and refactoring-hostile. So the non-initial let  
declarations for a given name in the same block would be ignored.

This leaves efficiency as a concern. If implementations do not do the  
analysis required to catch use before set at compile time, then let as  
well as const pays the read barrier price. It's non-trivial. Today let  
(and var in the absence of eval) can be optimized to use a read in  
the VM, possibly even a load instruction -- no getter barrier  
required. Whatever the GC write barrier cost, reads dominate and this  
is a significant savings.

On the other hand, computing SSA including dominance relations while  
parsing (in one pass) is possible so long as we do not add goto to the  
language. So maybe the analysis is acceptable to modern  
implementations, which are increasingly sophisticated.

Still, it is not yet agreed that let use before set shall be an error.  
It certainly is not the case for var, and working code counts on the  
undefined default initial value.

/be
___
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 Brendan Eich
On Oct 13, 2008, at 8:43 AM, Mark S. Miller 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? In that case, no problem with for being a SubStatement.

No one ever proposed otherwise for for (let...), and it would be nuts  
to do anything like that.


 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. If we can
 agree quickly on per-iteration, then

for (const x = ...) {...x...}

 should be allowed in ES3.1 (whether or not const hoists to block
 start). After ES3.1

for (const i :T[i] = ...) {...; a[i] = function(){...i...}; ...}

 would then mean what it should mean. Cool.

Agreed. See https://bugzilla.mozilla.org/show_bug.cgi?id=449811 --  
which is a bug we'd like to fix by following a spec.

/be
___
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 Brendan Eich
On Oct 13, 2008, at 3:51 PM, Waldemar Horwat wrote:

 Brendan Eich wrote:
 After some experiments, we decided for ES4 to make let and var the
 same at top level in a function or global code.

 This helped avoid implementation pain: very long scripts on the web,
 consisting of many statements in a row, motivate statement-wise
 parsing and cumulative code generation, which is straightforward in
 the absence of goto. Yet scope changes (e.g. due to a tardy rogue let
 x; after thousands of statements the first of which uses x) require a
 separate pass to generate the necessary block set-up code before the
 first use of x.

 Unifying let and var at top level also reduces the cognitive load
 (number of scopes in mind) and eliminates useless name shadowing
 opportunities.

 But such let/var unification at top level in a function body does
 leave bad old arguments[0] aliasing x in the above example, allowing
 mutation of otherwise lexical let x; (change var to let and fill in
 the ... with arguments[0] = 42; return x). The answer that we chose
 for ES4, and the one that's already agreeable in committee for
 Harmony, was deprecate arguments by providing optional and rest
 parameters.

 You can't do that.

Which that do you mean?


 function f() {
  x = 15;
  ...
  let t = some_runtime_expression;
  ...
  let x:t = ...
 }

 What is the type of x at the beginning of the function?

The example had better fail to compile.

I hope my point about implementations optimizing for very long AST  
hedge programs on the web is mixed up here. Such implementations  
build a full AST for function bodies, and function bodies tend to be  
reasonably short on the web (Tennent be damned). Long global code  
consisting of repeated assignment statements, OTOH, can suck up too  
much time and space if compiled as a whole instead of incrementally.

But I still don't know which that you meant.

/be
___
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 Brendan Eich
On Oct 13, 2008, at 3:56 PM, Waldemar Horwat wrote:

 Brendan Eich wrote:
 The agreement from the May TC39 meeting was that the declarations
 implicit (:*) and explicit annotations must normalize to the same
 type, or there's an error.

 That was back when the language had lots of requirements for compile- 
 time expressions, including on all types.  We agreed that that's not  
 part of ES-Harmony, and this condition doesn't make sense when type  
 expressions are evaluated at run time.

True enough -- but even without normalization, multiple equivalent (at  
runtime, depending on flow) annotations could be allowed. Should they  
be?

/be

___
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 Brendan Eich
On Oct 13, 2008, at 4:01 PM, Waldemar Horwat wrote:

 Brendan Eich wrote:
 If using an uninitialized let binding is an error, then hoisting is
 pointless except to make the statements between start of block and  
 the
 let declaration a dead zone for the binding name. This fits the
 ancient, weak but not entirely worthless post-hoc rationale for var
 hoisting (to avoid confusion among novice or inexperienced  
 programmers
 by making many scopes, each implicitly opened by var), but it's not
 particularly useful.

 This was our agreement from the ES4 days.  It's very useful, in that  
 it allows mutually recursive lambdas.

For function bindings, yes, of course -- but we were talking about let  
bindings (I thought). For let (there is no 'let function') bindings,  
how? Could you give an example?


 What's more, as discussed here and in TC39, repeated let declarations
 for the same binding name within the same block should be allowed.

 You can't do that in ES-Harmony.  There is no way to tell if the two  
 let declarations have the same type.

There has to be a way to answer the question are these two terms the  
same type at run-time.


 For orthogonality you'd also need to allow multiple const  
 declarations within the same scope, and I just don't want to go there.

I don't agree -- const and let are different keywords, they obviously  
differ in read-only vs. writable binding. They could differ otherwise.


 Anything else is user- and refactoring-hostile. So the non-initial  
 let
 declarations for a given name in the same block would be ignored.

 This is loaded language, but I can't tell how requiring there to be  
 a unique point of definition for a const or let is user-hostile.

My words were about let, not const. If let is the new var, then you  
either accept that re-declaration in the same block (usually function  
body) of the same name via var is common for good reason, and allow  
let to be used instead; or you raise the migration tax.

I do not mean to over-load the language, but we've seen a lot of code  
that redeclares using var (e.g. for (var i...) in adjacent for loops).  
We tried making a strict warning (error console spew) for  
redeclarations of same kind (var vs. var) four years ago (IIRC --  
Firefox 1 betas) and felt the heat from developers. We fell back on  
mixed var vs. function (const vs. anything is an error of course).

People on this list have argued similarly based on refactoring and var  
hoisting.

It may be that the migration tax must rise here, but I'd like to know  
why type annotations can't be equated at runtime.

/be
___
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 Brendan Eich
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++) ...

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.


  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.

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.


 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.

Assignment is not the issue, the binding's scope is.


 https://bugzilla.mozilla.org/show_bug.cgi?id=449811

 Like I said, it makes sense for 'for-each.'

Progress!

/be
___
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 Brendan Eich
On Oct 13, 2008, at 4:09 PM, Brendan Eich wrote:

 On Oct 13, 2008, at 4:01 PM, Waldemar Horwat wrote:

 Brendan Eich wrote:
 If using an uninitialized let binding is an error, then hoisting is
 pointless except to make the statements between start of block and
 the
 let declaration a dead zone for the binding name. This fits the
 ancient, weak but not entirely worthless post-hoc rationale for var
 hoisting (to avoid confusion among novice or inexperienced
 programmers
 by making many scopes, each implicitly opened by var), but it's not
 particularly useful.

 This was our agreement from the ES4 days.  It's very useful, in that
 it allows mutually recursive lambdas.

 For function bindings, yes, of course -- but we were talking about let
 bindings (I thought). For let (there is no 'let function') bindings,
 how? Could you give an example?

Obvious example:

   {
 let even = function (n) n == 0 || odd(n - 1);
 let odd  = function (n) n != 0  even(n - 1);
 print(even(42), odd(42));
 print(even(99), odd(99));
   }

My words about function binding meant to suggest: why not require  
users to write

   {
 function even(n) n == 0 || odd(n - 1);
 function odd(n)  n != 0  even(n - 1);
 ...
   }

But I'm not arguing that we shouldn't hoist let to top of block, only  
trying to justify my not particularly useful assertion ;-).

/be
___
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 Brendan Eich
On Oct 13, 2008, at 5:00 PM, Jon Zeppieri wrote:

 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.

Probably we're at cross purposes (I often am ;-) because of the primal  
sin in ECMAScript of specifying scope via object, and closure via  
scope chain capture.


 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.

Gotcha -- I agree, this is a problem for a proposal that tries to  
desugar for(;;). Curses.

The user expectation with a closure in a for(var i = 0; i  N; i++)  
loop, that each closure captures i's current value, remains,  
completely parallel to the for (i in o) ... case. Any attempt to solve  
it via let instead of var -- other than by making multiple (blech)  
scope (barf) objects, one per iteration -- must respecify how closures  
work. Hmm.

/be
___
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 Brendan Eich
On Oct 13, 2008, at 4:54 PM, Waldemar Horwat wrote:

 I am talking about let bindings.  Lars brought up at that meeting.   
 I did not find the use cases particularly convincing, but the dead  
 zone is compelling.  There are four ways to do this:
 A1. Lexical dead zone.  References textually prior to a definition  
 in the same block are an error.
 A2. Lexical window.  References textually prior to a definition in  
 the same block go to outer scope.
 B1. Temporal dead zone.  References temporally prior to a definition  
 in the same block are an error.
 B2. Temporal window.  References temporally prior to a definition in  
 the same block go to outer scope.

 Let's take a look at an example:

 let x = outer;
 function g() {return outer}

 {
  g();
  function f() { ... x ... g ... g() ... }
  f();
  var t = some_runtime_type;
  const x:t = inner;
  function g() { ... x ... }
  g();
  f();
 }

 B2 is bad because then the x inside g would sometimes refer to  
 outer and sometimes to inner.

 A1 and A2 introduce extra complexity but doesn't solve the problem.   
 You'd need to come up with a value for x to use in the very first  
 call to g().  Furthermore, for A2 whether the window occurred or not  
 would also depend on whether something was a function or not; users  
 would be surprised that x shows through the window inside f but g  
 doesn't.

 That leaves B1, which matches the semantic model (we need to avoid  
 referencing variables before we know their types and before we know  
 the values of constants).

Agreed, this is compelling, it shows the insufficiency of lexical order.

I missed this somehow (where are those meeting minutes? Still being  
vetted by TC39?). Thanks for restating it.

/be
___
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 Brendan Eich
On Oct 13, 2008, at 6:08 PM, Waldemar Horwat wrote:

 Brendan Eich wrote:
 Because presumably the let x:t became var x:t and var can't have
 types?

 Why can't var have a type annotation?

 Because a function can have many var declarations for the same  
 variable and because you can use the variable before any of the var  
 declarations are evaluated.  You can work out the implications  
 easily enough.  This has been brought up at meetings before.

Of course, ES4 had var x:t all over, but as you noted, different rules  
for evaluating t. Still, with new syntax comes the opportunity for  
reformed semantics, including restrictions on any bad var abusages  
we would like to move away from.

So my question remains (amended to be clear about what is the same):  
why does this mean we cannot equate let and var scope at the top  
level? I'm not talking about allowing them to mix in bad ways, or mix  
at all (see below). I'm talking about not having an implicit block  
around top-level function and global code.


  You wrote that you'd like let to become var (and unlike let as used  
 within an independent block) if used at the top level of a function:

Ok, sorry for being unclear. I do not mean to translate top-level  
'let' to 'var' and free let bindings from necessary restrictions. I do  
mean that let binds in the variable object, and let usage restricts  
other usage.

We can forbid mixed var x and let x at top level. We can require the  
same single definition for any let x at any level. We can forbid  
arguments usage if arguments[i] could alias a let binding, since let  
is new (along with rest and optional parameters to enable arguments  
deprecation).

But must we have an implicit block around programs and function bodies  
that contain let declarations, distinct from the variable scope  
(object)?


 What did you mean by had better fail to compile?  Other than the  
 type annotation, there is nothing about

 function f() {
  x = 15;
  ...
  var t = some_runtime_expression;
  ...
  var x:t = ...
 }

 that ought to fail to compile.

The assignment to x in that temporal dead zone before t's initializer  
has been evaluated.

Why is this different if you s/var x/let x/?

/be

___
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-13 Thread Brendan Eich
On Oct 13, 2008, at 7:48 PM, Mark S. Miller wrote:

 On Mon, Oct 13, 2008 at 5:00 PM, Jon Zeppieri [EMAIL PROTECTED] wrote:
 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.

Requirement 3 is met because var hoists to the enclosing function.  
This is the part I missed -- well done.

Note that continue; in body translates to break continueTarget; and  
break; translates to break breakTarget; -- you knew that ;-).

 However, in contradiction
 to my original claim, one couldn't usefully say const instead of
 let with a for(;;) loop.

Why not usefully? It's true the consts do not hoist to leave an effect  
in the variable object, but they do ensure const-ness. The body and  
update cannot mutate the nearest varName binding. This is sometimes  
useful and existing const implementations allow for (const...). I do  
not think it should be rejected just yet.

/be
___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: return when desugaring to closures

2008-10-14 Thread Brendan Eich
On Oct 14, 2008, at 7:38 AM, Neil Mix wrote:

 On Oct 13, 2008, at 6:39 PM, Brendan Eich wrote:

 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.

 Are you suggesting that closures over let capture bindings in the
 general case?  I hope not.  I think for loops are a special case,
 otherwise let is not the new var.  ;)

What about for-in loops?

I'm proceeding from user expectations being confounded. Something  
needs help here, possibly not for (;;) loops -- but almost certainly  
for-in loops containing closures capturing the loop variable.


 WRT for loops, it's important to remember that let provides an
 alternative that wasn't possible with var.  Suppose for moment we do
 *not* rebind on every iteration:

   for (let i = 0; i  objects.length; i++) {
 let j = i;
 objects[i].callback = function() {
   print(j);
 }
   }

Yes, this is in the bug I cited 
(https://bugzilla.mozilla.org/show_bug.cgi?id=449811 
). It is still a PITA.


 The syntactic overhead for such a workaround is much less than for  
 var:

   for (var i = 0; i  objects.length; i++) {
 objects[i].callback = buildCallback(i);
   }

   function buildCallback(i) {
 print(i);
   }

True, which makes it even more painful in some ways. Why doesn't JS  
do it for me? Closer, almost-but-not-quite-right, is torturous.


 The for/closures bug is definitely a newbie trap, but its pain is
 not its discovery, but the difficulty of working around it.  To me
 this could be a winning argument against re-binding on each loop,
 since re-binding precludes the (admittedly dubious) use-case of
 updating inside the body:

 for (let i = 0; i  100; i++) {
   if (skipAhead) {
 i += 9;
 continue;
   }
   ...
 }

So we can have our cake and eat it too with a tail-recursive  
desugaring that forwards the previous iteration's binding value to the  
next iteration's binding. Of course any practical implementation will  
have to do more analysis than is currently done in the top open-source  
implementations I've looked at. Could be worth the cost (VM hackers  
can take the cost for the larger team of users). What do you think?

/be
___
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 Brendan Eich
On Oct 14, 2008, at 7:17 AM, David-Sarah Hopwood wrote:

 This is subject to the criticism that the loop variable(s) are
 implicitly mutable in the update expression (only), when they were
 declared it to be const.

My point was simpler: sometimes it is handy to write for (const x...)  
and have no fresh binding for x, even though the loop iterates. It's a  
corner case that falls out of parsing var x and const x using the same  
top-down procedure, so not rejecting const where var is allowed. It  
arguably simplifies both implementation and user modeling of the  
grammar.

We could certainly reject for (const ...; ...; ...) loops if we saw  
this as an anti-use-case.


 No such criticism would apply to 'for each (const ...', though.

Right -- this is pure win.

/be
___
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 Brendan Eich
On Oct 14, 2008, at 7:17 AM, David-Sarah Hopwood wrote:

 Requirement 3 is met because var hoists to the enclosing function.

 Assuming that var hoisting is done before this expansion, yes.

Absolutely -- var hoisting across lambdas to preserve TCP is prior  
magic, assumed by the (revised) lambda proposal. In principle it could  
be lambda coded but I don' t believe the result would be particularly  
illuminating.

/be
___
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 Brendan Eich
On Oct 14, 2008, at 12:39 PM, Waldemar Horwat wrote:

 PS.  What does lambda(x = y){...}() mean?  Is it different from  
 lambda(x){...}(y)?

No.

  What does lambda(x = y){...}(z) do when z is undefined?

Passes undefined bound to x. Undefined is not the same as missing.

These are my answers based on past default parameter proposals from  
ES4 which met with approval at the Oslo meeting. Others will no doubt  
shout if they seem wrong.

/be

___
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 Brendan Eich

On Oct 14, 2008, at 1:36 PM, Brendan Eich wrote:


On Oct 14, 2008, at 12:39 PM, Waldemar Horwat wrote:

What does lambda(x = y){...}(z) do when z is undefined?


Passes undefined bound to x. Undefined is not the same as missing.


Lest anyone think otherwise, missing means actual argument count is  
less than number of formal parameters. It's not yet another undefined- 
like value code.


The implementation knows that lambda has arity 1 with a default  
parameter value. It knows the call passes an actual (that its value is  
undefined does not matter). So the default parameter value is not used.


Default parameters are evaluated once when the lambda expression is  
evaluated. That the lambda is immediately applied in your questions'  
examples may make this point unclear. This is why my answer to your  
question:



lambda(x = y){...}() mean?  Is it different from
lambda(x){...}(y)



was No. But if you captured the lambda and applied it elsewhere to a  
different y (y in a different scope chain), this equivalence would not  
hold. Hope this is all non-controversial (modulo blunders on my part  
explaining it).


/be___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: return when desugaring to closures

2008-10-15 Thread Brendan Eich

On Oct 15, 2008, at 2:36 PM, Waldemar Horwat wrote:


There is no such thing as a let expression.


Let expressions in JS1.7 (Firefox 2+), based on the ES4 proposal. ES3- 
ish grammar:


LetExpression :
  let ( VariableDeclarationList ) [lookahead ∉ {{}]  
AssignmentExpression


produced from PrimaryExpression.


It's mandatory because the grammar and semicolon insertion rules say  
so.  Btw, to properly terminate a lambda expression you'd need *two*  
semicolons.  Here's why one would be insufficient:


f = lambda(x) x;
(a + b)  c;

would parse the body of the lambda as the expression x;, the (a +  
b) as an argument to the lambda, and the rest as applying to the  
result of calling the lambda.  What you'd want to write instead  
would be:


f = lambda(x) x;;


Expression closures in JS1.8 (Firefox 3+) do not have this problem.  
Using ES3's notation:


FunctionDeclaration :
  function Identifier ( FormalParameterListopt ) FunctionBody
FunctionExpression :
  function Identifieropt ( FormalParameterListopt ) FunctionBody
FormalParameterList :
  Identifier
  FormalParameterList , Identifier
FunctionBody :
  { SourceElements }
  [lookahead ∉ {{}] AssignmentExpression

/be___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: return when desugaring to closures

2008-10-15 Thread Brendan Eich


On Oct 15, 2008, at 6:13 PM, Brendan Eich wrote:


On Oct 15, 2008, at 2:36 PM, Waldemar Horwat wrote:


There is no such thing as a let expression.


Let expressions in JS1.7 (Firefox 2+), based on the ES4 proposal.  
ES3-ish grammar:


LetExpression :
  let ( VariableDeclarationList ) [lookahead ∉ {{}]  
AssignmentExpression


Rather,

LetExpression :
  let ( VariableDeclarationList ) AssignmentExpression

/be

___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Lambda vs. function

2008-10-16 Thread Brendan Eich
On Oct 16, 2008, at 1:55 PM, Waldemar Horwat wrote:

 var:  Not an issue if you're not using var inside the lambda.  Code  
 generation that wants to use lambda would use var why?

 arguments:  Again, not an issue if you're not using the arguments  
 array.  If a code generator is updated for lambda, then presumably  
 it will be updated not to use the arguments array.

Why assume that lambda is only for code generators?

/be
___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: return when desugaring to closures

2008-10-16 Thread Brendan Eich

On Oct 16, 2008, at 1:20 PM, Waldemar Horwat wrote:

I don't think you can come up with a consistent shift or greedy  
notion.


Funny, yacc has had one for decades, used to resolve dangling-else.



The one you may be thinking of will happily accept code such as

let (a = 5) x + y.foo = 2;

yet the Firefox code gives a syntax error for it despite it being  
parsable by your grammar.


Cut the misattribution of your ideas to me, based on misinterpretation  
of your experiment. Here's what's going on:


Firefox (SpiderMonkey, shown here via its REPL) throws an error:

js y = {}
[object Object]
js let (a = 5) x + y.foo = 2
typein:2: SyntaxError: invalid assignment left-hand side:
typein:2: let (a = 5) x + y.foo = 2
typein:2: ..^

This is an error required by ES3, but it is not a syntax error  
according to the ES3 grammar -- it is an error due to semantic  
checking done in the spec by PutValue:


11.13.1 Simple Assignment ( = )
The production AssignmentExpression : LeftHandSideExpression =  
AssignmentExpression is evaluated as follows:

1. Evaluate LeftHandSideExpression.
2. Evaluate AssignmentExpression.
3. Call GetValue(Result(2)).
4. Call PutValue(Result(1), Result(3)).
5. Return Result(3).

8.7.2 PutValue (V, W)
1. If Type(V) is not Reference, throw a ReferenceError exception.
2. Call GetBase(V).
3. If Result(2) is null, go to step 6.
4. Call the [[Put]] method of Result(2), passing GetPropertyName(V)  
for the property name and W for the value.

5. Return.
6. Call the [[Put]] method for the global object, passing  
GetPropertyName(V) for the property name and W for the

value.
7. Return.

SpiderMonkey historically used SyntaxError, not ReferenceError, and  
throw at compile-time. This pre-dates ES1. Another example not  
involving let expressions:


js a + b = c
typein:1: SyntaxError: invalid assignment left-hand side:
typein:1: a + b = c
typein:1: ..^

From ES3 chapter 16:

An implementation may treat any instance of the following kinds of  
runtime errors as a syntax error and therefore

report it early:
• Improper uses of return, break, and continue.
• Using the eval property other than via a direct call.
• Errors in regular expression literals.
• Attempts to call PutValue on a value that is not a reference (for  
example, executing the assignment statement

3=4).

You may object that we should throw ReferenceError not SyntaxError --  
that is not entirely clear from the chapter 16 wording, but it is at  
most a bug unrelated to our disagreement, and it doesn't prove any  
claim that primary expressions ending in assignment expressions are  
ambiguous or unusable.




So what's the real problem?


I said it already.  The problem is that you don't have a valid  
grammar.


You have not demonstrated that claim.


 This one is invalid, so the code of the Firefox implementation is  
effectively the specification, and it's hard to reason about that.


It's easy, you can do it ;-).



Other examples:  What does the following do?

for (a = let (b = c) b in d) ...


SyntaxError because no ; after first expression in for (;;) loop head.



vs.
for (a = let (b = c) b in d;;) ...


Valid syntax.



vs.
for (a = let (b = c) b in d in d) ...


SyntaxError because no ; after first expression in for (;;) loop head.

Yes, you can chain in (relational) expressions within an  
AssignmentExpression. No, users are not flummoxed, or as far as we can  
tell in over two years even bothered, by this. Yes, it can be  
specified unambiguously.


/be___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: return when desugaring to closures

2008-10-16 Thread Brendan Eich
On Oct 15, 2008, at 1:28 PM, Mark S. Miller wrote:

 On Wed, Oct 15, 2008 at 12:31 PM, Dave Herman [EMAIL PROTECTED]  
 wrote:
 Do you prefer (lambda Formals Block | lambda Formals Expression)?
 [Personally I'm fine with that.] Or do you oppose any lambda  
 expressions
 at all? Or did you have something else in mind?

 My preference is

lambda Formals? Block

 Since an invocation of the closure evaluates to its completion value,
 the only savings of introducing the Expression form would be a pair of
 curlies. This is too small a benefit to justify another case in the
 grammar. Further, in exchange for always requiring the curlies, we can
 make the formals optional. Once we've got lambda, we'll start using
 them for control abstractions, in which case the no-parameter form
 will become quite common. I'd rather be able to leave out the parens
 than the curlies. YMMV. This is admittedly subjective, but you did ask
 about preferences.

Hi Mark,

That's fair and closely reasoned, but I question the likelihood of  
zero-argument lambdas emerging in control abstractions favored by all  
that many users. For now I favor the lambda expression form as well as  
the lambda block form. You're right that much of this is subjective,  
not just personal but also speculative about what users will tend to  
use.

Expression closures are already insanely popular in JS1.8, of course  
used only in Mozilla-specific code. They'd be even more winning as  
lambdas, whether zero args is common or not (six letter keyword  
instead of eight), but losing the braces is part of the win. The two  
shifted chars are not easy on some peoples' hands (ask Python hackers  
who are spared such RSI-inducing chords). The visual weight is less,  
to boot.

Definitely my two cents, no more (possibly fewer ;-).

/be
___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: return when desugaring to closures

2008-10-16 Thread Brendan Eich
On Oct 16, 2008, at 3:33 PM, Brendan Eich wrote:

 SpiderMonkey historically used SyntaxError, not ReferenceError, and  
 throw at compile-time. This pre-dates ES1. Another example not  
 involving let expressions:

 js a + b = c
 typein:1: SyntaxError: invalid assignment left-hand side:
 typein:1: a + b = c
 typein:1: ..^

 From ES3 chapter 16:

 An implementation may treat any instance of the following kinds of  
 runtime errors as a syntax error and therefore
 report it early:
 • Improper uses of return, break, and continue.
 • Using the eval property other than via a direct call.
 • Errors in regular expression literals.
 • Attempts to call PutValue on a value that is not a reference (for  
 example, executing the assignment statement
 3=4).

 You may object that we should throw ReferenceError not SyntaxError  
 -- that is not entirely clear from the chapter 16 wording,


An implementation may treat any instance of the following kinds of  
runtime errors as a syntax error and therefore report it early seems  
clear enough: an implementation that does choose (may) to report the  
ReferenceError from 8.7.2 PutValue step 1 *must* treat that runtime  
error as a syntax error -- throw a SyntaxError, in other words.  
There's no SpiderMonkey bug here, and it would be incorrect to do  
other than change ReferenceError to SyntaxError when reporting the  
PutValue error at compile time.

Again, this is not a grammatical error. The ES3 grammar is not enough  
to decide what syntax errors might result from feeding a given program  
source to an implementation.

/be
___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: return when desugaring to closures

2008-10-17 Thread Brendan Eich
On Oct 17, 2008, at 11:05 AM, Waldemar Horwat wrote:

 Brendan Eich wrote:
 Is this a perfectly valid for-in statement?

 for (a = b in c);

 Not according to ES3's grammar. An assignment expression is not  
 valid on
 the left of the for-in's in:

 /IterationStatement /*:*
 *  ...*
 *  for ( */LeftHandSideExpression /*in */Expression /*) */ 
 Statement/
 *  for ( var */VariableDeclarationNoIn /*in */Expression /*)

(Note VariableDeclarationNoIn after var.)



 */Statement/

 LeftHandSideExpression does not produce an unparenthesized
 AssignmentExpression, and if  you parenthesize then PutValue will  
 throw
 on the non-Reference result of the assignment, the ReferenceError at
 runtime which again can become SyntaxError at compile time.

 I accidentally took out the var in editing the message.  It should  
 have been

 for (var a = ...)

Waldemar
 _

In that case the -NoIn sub-grammar should apply, extended to  
LetExpressionNoIn. So

for (let (a = b) c in d);

would do what you want. We would have to change SpiderMonkey for this  
edge case, but that is our problem (and unlikely to break anyone).

/be

___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: return when desugaring to closures

2008-10-17 Thread Brendan Eich
On Oct 17, 2008, at 11:30 AM, Brendan Eich wrote:

 In that case the -NoIn sub-grammar should apply, extended to
 LetExpressionNoIn. So

 for (let (a = b) c in d);

Sorry, of course that should have been

for (var a = let (b = c) b in d);

/be
___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: The trouble with ambiguous grammars

2008-10-17 Thread Brendan Eich
On Oct 17, 2008, at 12:25 PM, Waldemar Horwat wrote:

 Here's a clearer case that Firefox gets wrong (or your grammar gets  
 wrong, depending on your point of view):

 function f() {return f}
 var x = 3;
 let (a = 1) a ? f : x++();

 The grammar states that the last statement must evaluate to f.   
 Firefox gives a syntax error.  This is incorrect because the let  
 expression up to the ++ is a PrimaryExpression so can be used as the  
 left operand of a function call.

Consider the simpler, let-expression-free test:

js var a = 1, f = 2;
js a ? f : x++();
typein:3: SyntaxError: missing ; before statement:
typein:3: a ? f : x++();
typein:3: .^

(The error pointer is off by two, I'm filing a bug on that.)

Safari and IE seem to agree (IE blames the correct column number, the  
one for the ( -- good for it).

This is an error according to ES1-3 because x++ is a postfixExpression  
derived from

PostfixExpression :
   LeftHandSideExpression
   LeftHandSideExpression [no LineTerminator here] ++
   LeftHandSideExpression [no LineTerminator here] --

while expr() meaning call expr with zero arguments derives from

CallExpression : MemberExpression Arguments

and MemberExpression is never an unparenthesized PostfixExpression:

MemberExpression :
   PrimaryExpression
   FunctionExpression
   MemberExpression [ Expression ]
   MemberExpression . Identifier
   new MemberExpression Arguments

So your example with or without the leading let (a = 1) is not  
syntactically valid.


 In an ambiguous grammar, you also need to prove the negative:  no  
 *other* expansion can match that source program and shadow your  
 expansions.  Proving the negative causes trouble because a language  
 extension could turn the mismatch into a match and because  
 sometimes, as in the above case, you expected some other part of the  
 grammar to shadow your expansions but it didn't.

That's a good point, but it is not what is going on here. There is no  
valid sentence x++() produced by ES1-3's expression grammar.

/be
___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: The trouble with ambiguous grammars

2008-10-17 Thread Brendan Eich
On Oct 17, 2008, at 3:39 PM, Brendan Eich wrote:

 On Oct 17, 2008, at 12:25 PM, Waldemar Horwat wrote:

 Here's a clearer case that Firefox gets wrong (or your grammar gets
 wrong, depending on your point of view):

 function f() {return f}
 var x = 3;
 let (a = 1) a ? f : x++();

 The grammar states that the last statement must evaluate to f.
 Firefox gives a syntax error.  This is incorrect because the let
 expression up to the ++ is a PrimaryExpression so can be used as the
 left operand of a function call.

Er, you are right, I should have acknowedged this point. The rest of  
my post is about x++() not being a valid sentence, which supports your  
argument.

While we don't have any usability problems, and torturous statements  
such as

let (a = 1) a ? f : x++();

are not written by real users (they'd parenthesize to clear up  
things), I agree that we don't want the prove a negative problem.

/be

___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


  1   2   3   4   5   6   7   8   9   10   >