Re: Opt-in versioning

2008-07-21 Thread Michael Haufe
Jon Zeppieri wrote:
> On Mon, Jul 21, 2008 at 8:58 PM, Michael Haufe <[EMAIL PROTECTED]> wrote:
>   
>> So let me see if I understand this argument correctly.
>> 
>
> I generally agree with what you've written here -- just a couple of 
> comments...
>
>   
>> If I want the benefits of this blocking, does that mean I have to give
>> up some of my shorthand?
>>
>> (a === b) ? true : false;
>>
>> How would the block work in this case?
>> 
>
> Not sure what you're getting at here.  What block are you referring to?
>
>   
>> The JavaScript 1.7 let statement is already the better block we need,
>> and instead of being a generic solution like the one you've suggested,
>> it has flexibility and doesn't force me to change the way I already code
>> things:
>> 
>
> I'm partial to the let statement, too, but you should know that it's
> not being proposed for either ES3.1 or ES4.  But yes, it makes the
> scope of the let-bound variables perfectly clear -- let vs. let*
> binding semantics aside.  (Does the JS1.7 let statement bind
> sequentially or in parallel?)
>
> -Jon
>
>
>   

I was basically asking if these two structures were supposed to be 
equivalent and part of what he was suggesting:

if(a === b){
   foo;
}
else{{
   bar;
}}
_

(a === b) ? foo : {{ bar }};





___
Es4-discuss mailing list
Es4-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es4-discuss


Re: Opt-in versioning

2008-07-21 Thread Jon Zeppieri
On Mon, Jul 21, 2008 at 8:58 PM, Michael Haufe <[EMAIL PROTECTED]> wrote:
> So let me see if I understand this argument correctly.

I generally agree with what you've written here -- just a couple of comments...

> If I want the benefits of this blocking, does that mean I have to give
> up some of my shorthand?
>
> (a === b) ? true : false;
>
> How would the block work in this case?

Not sure what you're getting at here.  What block are you referring to?

>
> The JavaScript 1.7 let statement is already the better block we need,
> and instead of being a generic solution like the one you've suggested,
> it has flexibility and doesn't force me to change the way I already code
> things:

I'm partial to the let statement, too, but you should know that it's
not being proposed for either ES3.1 or ES4.  But yes, it makes the
scope of the let-bound variables perfectly clear -- let vs. let*
binding semantics aside.  (Does the JS1.7 let statement bind
sequentially or in parallel?)

-Jon
___
Es4-discuss mailing list
Es4-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es4-discuss


Opt-in versioning

2008-07-21 Thread Michael Haufe
So let me see if I understand this argument correctly.

{{...}} means the same thing as a generic "let" statement and {{...}} is 
optional
 Because it's optional, the language should contain both "let" and {{...}}?

I don't see how this doesn't add a level of complexity.Instead of just 
remembering how I declared my variable I would also have to see what 
kind of block I put it in. If my program has 1500+ lines of code, this 
isn't exactly going to be clear, especially if the whitespace is nasty 
and the "{{" isn't on the same line, nor indented properly . "let" 
clearly states that this variable is bound by its block and  I just have 
to find the "{ }". var means its clearly bound by its function and I 
just have to find where the "function" is.

I assume with these rules the following is legal?

if(a){
   
}
else{{

}}

If I want the benefits of this blocking, does that mean I have to give 
up some of my shorthand?

(a === b) ? true : false;

How would the block work in this case?

The JavaScript 1.7 let statement is already the better block we need, 
and instead of being a generic solution like the one you've suggested, 
it has flexibility and doesn't force me to change the way I already code 
things:

var x = 5;
var y = 0;

let (x = x+10, y = 12) {
  print(x+y + "\n");
}

---
var x = 5;
var y = 0;
document.write( let(x = x + 10, y = 12) x+y  + "\n");
---
if (x > y){
   let gamma = 12.7 + y;
   i = gamma * x;
}

document.write(x+y + "\n");
print((x + y) + "\n");

---
for (let expr1; expr2; expr3) statement  where expr2, expr3, and statement are 
local
---

How would you're "better block" work as a viable alternative without creating 
more work or doing what can already be done by let?

Examples from http://developer.mozilla.org/en/docs/New_in_JavaScript_1.7



___
Es4-discuss mailing list
Es4-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es4-discuss


Re: Surprising semantics

2008-07-21 Thread Ingvar von Schoultz
Waldemar Horwat wrote:
> The problem is that you then get a plethora of ways
> to define things:
> [...]
> Furthermore, some of them don't make sense (such as
> "function" without "let") because they can conditionally
> capture variables that may not even exist.

Despite very much searching in the discussion archives I can't
find a single description that convinces me that there is in
fact a problem. My analyses find simple solutions for all the
situations I can think of, including nonexistent let variables.

But maybe I just haven't understood the problem. Could you give
me a link to a description?

In my analyses, all you need to do is specify what |function|
without |let| is supposed to mean, in a way that is well suited
to how ECMAScript declarations behave.

You get useful, helpful semantics, and proper throwing of errors
on incorrect access, with simple implementation, if you think how
you would manually make the function name accessible in the outer
scope, and then let the compiler make that very arrangement. The
result is useful and intuitive and avoids peculiar irregularities.

Of course it works only if it can be handled with rules that are
simple enough that the compiler can deal with all cases. I'll take
this in steps to show that the rules become simple enough.

Consider the semantics of a standard function declaration-and-
definition-combined:

 Fn();
 function Fn() {return 1}

As with any declaration in ECMAScript, the declaration of the name
Fn takes effect before you enter the scope.

This name gets the special treatment that is afforded to functions:
It is assigned its value before you enter the scope. This value is
the function object. So the call to Fn is successful.

Consider the difference when it's conditional:

 Fn();
 if (Unknown)
 function Fn() {return 1}
 else
 function Fn() {return 2}

Again, as with any declaration, the declaration of the name takes
effect before you enter the scope.

However, in this case it can't be assigned any value before you
enter the scope, since there isn't any known value. Fn exists but
is unassigned, it has the special value |undefined|. The call to
Fn() throws an error as an attempt to call undefined().

The above is equivalent to the following, which is how you would
do the same thing manually if you wanted the same result including
the bug:

 var Fn;   // Automatically assigned the value |undefined|.
 Fn();
 if (Unknown)
 Fn = function Fn() {return 1}
 else
 Fn = function Fn() {return 2}

So where the programmer wrote function declarations the compiler
arranges assignment in cases like these.

Even though this changes the behavior of function(), in that the 
assignment comes later than usual, this is not a case of hidden
surprising semantics. The programmer did specify that the function
Fn depends on if(Unknown). This obeys what the programmer said.

It would be wrong to decide upon one of the two functions and assign
that before scope entry, as it would violate the requirement that
Fn depend on if(Unknown). What's more, even if the condition is
known at compilation time, the programmer is using a construct
that is intrinsically sequential. So regardless of what is known,
the most exact interpretation is still to maintain the sequential
nature. This way you get simple, consistent semantics.

Let's move the function call into a block and have Fn hoist out
of that:

 print (Fn);
 if (Unknown)
 {  Fn();
function Fn() {return 1}   // Hoisted to global scope.
 }

The compiler should do this:

 var Fn; // Hoisted name, assigned the value |undefined|.
 print (Fn);
 if (Unknown)
 {  Fn = HiddenName; // Early assignment at beginning of block.
 Fn();
function HiddenName() {return 1}
 }

(Except the function knows itself as Fn rather than HiddenName.)

Here the name Fn cannot have a value at the beginning of the global
scope, but it can have a value at the beginning of the block where
it's declared-and-defined.

The special treatment of functions, where the compiler moves the
assignment to the beginning of the block, should happen when the
compiler can determine that this is correct, using simple rules,
rules that are simple not only for the compiler but also for the
programmer. In any situation where the compiler can't easily
determine this, it assigns |undefined| at block entry, and then
assigns function object at the spot where the function is defined.

There may be two block-entry points to consider, as above.

Let's hoist with a nonexistent let variable:

 Fn();
 if (Unknown)
 {   let LetVal = 3;  // Nonexistent when Fn() is called.
 if (Maybe)
 {   function Fn()// Hoisting to Outer.
 {   return LetVal;   // Return the let variable.
 }
 }
 }

This is just like the other cases. At the beginning of the global
scope the name Fn exists and has the value