Continuing woes in reading the ES6 spec language

Brendan Eich brendan at mozilla.com
Sun Sep 15 16:26:20 PDT 2013


> Brendan Eich <mailto:brendan at mozilla.com>
> September 15, 2013 7:22 PM
>
>
> What other languages?
>
> Say a = 4 outside. Then
>
> foo(1, 2)
>
> should bind x = 1, y = 2, and z = undefined

Sorry, I botched the example.

Remind me not to mail while jetlagged.

Trying again:

a = 4
b = 5
function foo(x, y = a, z = b) {...}

foo(1, 2)

My point was that simply because 2 of 3 arguments were supplied and y 
has a default, we should not skip it and bind 2 to z. In this fixed 
example, z defaults to b = 5, no other choice. Right?

/be


> -- it should not skip y just because y has a parameter default value 
> and bind 2 to z.
>
> /be
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
> Oliver Hunt <mailto:oliver at apple.com>
> September 15, 2013 11:59 AM
> On Sep 13, 2013, at 7:19 PM, Brendan Eich<brendan at mozilla.com>  wrote:
>
>>> Axel Rauschmayer<mailto:axel at rauschma.de>
>>> September 14, 2013 12:36 AM
>>>
>>> Thanks! I didn’t look at the spec section, I (incorrectly) assumed I knew how they worked. Then I don’t see a use case for this, I’d find it confusing.
>> What alternative do you want?
>>
>> 1. Parameter default value before default-free parameter means call without arity match throws?
>>
>> 2. What Oliver may have feared in switching to named parameters: actual argument list shorter than formal list with default on left causes parameter binding to skip defaults? This is not coherent:
>>
>> function foo(x, y = a, z = y) {...}
>>
>> foo()        // x=undefined, y=a, z=a
>> foo(1)       // x=1, y=a, z=a
>> foo(1, 2)    // x=1, y=a, z=2???
> Why the ???
>
> This makes sense, and it is what other languages with default values do
>
>> foo(1, 2, 3) // x=1, y=2, z=3
>>
>> 3. What ES6 draft says.
>>
>> /be
>>> -- 
>>> Dr. Axel Rauschmayer
>>> axel at rauschma.de<mailto:axel at rauschma.de>
>>>
>>> home: rauschma.de<http://rauschma.de>
>>> twitter: twitter.com/rauschma<http://twitter.com/rauschma>
>>> blog: 2ality.com<http://2ality.com>
>>>
>>> _______________________________________________
>>> es-discuss mailing list
>>> es-discuss at mozilla.org
>>> https://mail.mozilla.org/listinfo/es-discuss
>>> Axel Rauschmayer<mailto:axel at rauschma.de>
>>> September 13, 2013 11:06 PM
>>>
>>> As an aside: This can be useful. For example:
>>>
>>> ```js
>>> function getRandomInteger(lower = 0, upper) {
>>>     return Math.floor(Math.random() * (upper - lower)) + lower;
>>> }
>>> ```
>>>
>>> Implementing this function in some other manner is much more complicated.
>>>
>>> But I agree that you want to name parameters if there are more than 2.
>>>
>>> -- 
>>> Dr. Axel Rauschmayer
>>> axel at rauschma.de<mailto:axel at rauschma.de>
>>>
>>> home: rauschma.de<http://rauschma.de>
>>> twitter: twitter.com/rauschma<http://twitter.com/rauschma>
>>> blog: 2ality.com<http://2ality.com>
>>>
>>> _______________________________________________
>>> es-discuss mailing list
>>> es-discuss at mozilla.org
>>> https://mail.mozilla.org/listinfo/es-discuss
>>> Oliver Hunt<mailto:oliver at apple.com>
>>> September 13, 2013 5:39 PM
>>> On Sep 13, 2013, at 9:18 AM, Brendan Eich<brendan at mozilla.com>   wrote:
>>>
>>>>> Oliver Hunt<mailto:oliver at apple.com>
>>>>> September 13, 2013 6:11 PM
>>>>> Okay so we were discussing among ourselves, and we thought that a sane "desugaring" for
>>>>>
>>>>> function f(x=expr) {
>>>>> ...
>>>>> }
>>>>>
>>>>> would be
>>>>>
>>>>> function f(x) {
>>>>> if (arguments.length<   1) x=expr;
>>>>> ...
>>>>> }
>>>> ES6 has two things that go against this, already in consensus among those at the meetings (we miss you shiny fruit-company people ;-):
>>> More of the consensus discussion need to happen on es-discuss, this is the only standards body i'm involved in that seems to require details be hammered out in F2F meetings.  It's one of the things I find disappointing about the ES standard - the avoidance of es-discuss when discussing language features makes it actively difficult for input from the wider dev community.
>>>
>>>> * You can have default parameters before parameters without defaults.
>>> The spec explicitly states that any parameter without a default, but after another parameter that does have a default assignment implicitly has a default property of undefined
>>>
>>>> * You can pass undefined to trigger defaulting -- this is important for composition / delegation.
>>> No, it's a terrible feature :D i'm unaware of any language that supports arbitrary ordering of arguments.
>>>
>>> The elegant solution i saw someone mention was
>>>
>>> function f({option1, option2, option3} = {option1:default option1, ...}) { … }
>>>
>>> That gives you nicely named parameters!  (It was this example that made me start looking at default parameters in the first place)
>>>
>>>
>>>> I think we all agree that new formal parameter syntax gets rid of arguments. Yay!
>>> If only we could kill it everywhere!  My proposal was to simply ban arguments as an identifier entirely
>>>
>>>> The real issue that Andreas's proposal addressed was the insanity of body declarations hoisting to be in view of default. But it sounds like we do not have consensus on whether or not that's crazy.
>>>>> This would produce a consistent and easy to follow semantic for default evaluation, it doesn't introduce any new types of scope, nor does it require any new concepts (temporal dead zones, etc) to be learned by a developer who just wants default parameter values.
>>>> The hoisting issue still hits your non-consensus actual parameter count (arguments.length) thing, though. When reading the function in source order, one sees a default expression. Mentally moving the defaulting to the body means that hoisted body decls trump outer bindings for names in the expression, indeed. But mentally moving is the objectionable part -- cognitive load, and non-source-order evaluation (more hoisting).
>>>>
>>>> Hoisting need not perpetuate itself this way. We can do better, or at least Andreas proposes that we do. I'm sympathetic.
>>>>
>>>> Temporal dead zones are indeed weirder but perhaps pay for themselves by catching errors. But is it an error to use an outer name binding in the default expression, given its position in the formal parameter list? I think not.
>>> The problem with temporal dead zones is that they lead to weird behaviour in edge cases, and almost all of them should be syntactically identifiable as errors up front.  The problem is that you can only _almost_ get syntax checked behaviour upfront because eval.
>>>
>>>>> We also felt that if you use default or rest parameters we should consider that as a opt out from the magic arguments object, and just poison the arguments identifier entirely (no read, write, or declare)
>>>> SpiderMonkey's prototype implementation does this, and I asserted above that ES6 specs it. Not so?
>>> The ES6 spec (as far as i can read it) only bans declaration of parameters/vars named "arguments" it doesn't ban reading them.
>>>
>>>> /be
>>>>
>>> _______________________________________________
>>> es-discuss mailing list
>>> es-discuss at mozilla.org
>>> https://mail.mozilla.org/listinfo/es-discuss
>>>
>>> Brendan Eich<mailto:brendan at mozilla.com>
>>> September 13, 2013 5:18 PM
>>>> Oliver Hunt<mailto:oliver at apple.com>
>>>> September 13, 2013 6:11 PM
>>>> Okay so we were discussing among ourselves, and we thought that a sane "desugaring" for
>>>>
>>>> function f(x=expr) {
>>>> ...
>>>> }
>>>>
>>>> would be
>>>>
>>>> function f(x) {
>>>> if (arguments.length<  1) x=expr;
>>>> ...
>>>> }
>>> ES6 has two things that go against this, already in consensus among those at the meetings (we miss you shiny fruit-company people ;-):
>>>
>>> * You can have default parameters before parameters without defaults.
>>>
>>> * You can pass undefined to trigger defaulting -- this is important for composition / delegation.
>>>
>>> I think we all agree that new formal parameter syntax gets rid of arguments. Yay!
>>>
>>> The real issue that Andreas's proposal addressed was the insanity of body declarations hoisting to be in view of default. But it sounds like we do not have consensus on whether or not that's crazy.
>>>> This would produce a consistent and easy to follow semantic for default evaluation, it doesn't introduce any new types of scope, nor does it require any new concepts (temporal dead zones, etc) to be learned by a developer who just wants default parameter values.
>>> The hoisting issue still hits your non-consensus actual parameter count (arguments.length) thing, though. When reading the function in source order, one sees a default expression. Mentally moving the defaulting to the body means that hoisted body decls trump outer bindings for names in the expression, indeed. But mentally moving is the objectionable part -- cognitive load, and non-source-order evaluation (more hoisting).
>>>
>>> Hoisting need not perpetuate itself this way. We can do better, or at least Andreas proposes that we do. I'm sympathetic.
>>>
>>> Temporal dead zones are indeed weirder but perhaps pay for themselves by catching errors. But is it an error to use an outer name binding in the default expression, given its position in the formal parameter list? I think not.
>>>> We also felt that if you use default or rest parameters we should consider that as a opt out from the magic arguments object, and just poison the arguments identifier entirely (no read, write, or declare)
>>> SpiderMonkey's prototype implementation does this, and I asserted above that ES6 specs it. Not so?
>>>
>>> /be
>>>
>>> _______________________________________________
>>> es-discuss mailing list
>>> es-discuss at mozilla.org
>>> https://mail.mozilla.org/listinfo/es-discuss
>>>
>>> Oliver Hunt<mailto:oliver at apple.com>
>>> September 13, 2013 5:11 PM
>>> Okay so we were discussing among ourselves, and we thought that a sane "desugaring" for
>>>
>>> function f(x=expr) {
>>> ...
>>> }
>>>
>>> would be
>>>
>>> function f(x) {
>>> if (arguments.length<  1) x=expr;
>>> ...
>>> }
>>>
>>> This would produce a consistent and easy to follow semantic for default evaluation, it doesn't introduce any new types of scope, nor does it require any new concepts (temporal dead zones, etc) to be learned by a developer who just wants default parameter values.
>>>
>>> We also felt that if you use default or rest parameters we should consider that as a opt out from the magic arguments object, and just poison the arguments identifier entirely (no read, write, or declare)
>>>
>>> --Oliver
>>>
>>>
>>>
>>>
>>> _______________________________________________
>>> es-discuss mailing list
>>> es-discuss at mozilla.org
>>> https://mail.mozilla.org/listinfo/es-discuss
>>>
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>
>
> Brendan Eich <mailto:brendan at mozilla.com>
> September 13, 2013 10:19 PM
>> Axel Rauschmayer <mailto:axel at rauschma.de>
>> September 14, 2013 12:36 AM
>>
>> Thanks! I didn’t look at the spec section, I (incorrectly) assumed I 
>> knew how they worked. Then I don’t see a use case for this, I’d find 
>> it confusing.
>
> What alternative do you want?
>
> 1. Parameter default value before default-free parameter means call 
> without arity match throws?
>
> 2. What Oliver may have feared in switching to named parameters: 
> actual argument list shorter than formal list with default on left 
> causes parameter binding to skip defaults? This is not coherent:
>
> function foo(x, y = a, z = y) {...}
>
> foo() // x=undefined, y=a, z=a
> foo(1) // x=1, y=a, z=a
> foo(1, 2) // x=1, y=a, z=2???
> foo(1, 2, 3) // x=1, y=2, z=3
>
> 3. What ES6 draft says.
>
> /be
>>
>> -- 
>> Dr. Axel Rauschmayer
>> axel at rauschma.de <mailto:axel at rauschma.de>
>>
>> home: rauschma.de <http://rauschma.de>
>> twitter: twitter.com/rauschma <http://twitter.com/rauschma>
>> blog: 2ality.com <http://2ality.com>
>>
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>> Axel Rauschmayer <mailto:axel at rauschma.de>
>> September 13, 2013 11:06 PM
>>
>> As an aside: This can be useful. For example:
>>
>> ```js
>> function getRandomInteger(lower = 0, upper) {
>> return Math.floor(Math.random() * (upper - lower)) + lower;
>> }
>> ```
>>
>> Implementing this function in some other manner is much more 
>> complicated.
>>
>> But I agree that you want to name parameters if there are more than 2.
>>
>> -- 
>> Dr. Axel Rauschmayer
>> axel at rauschma.de <mailto:axel at rauschma.de>
>>
>> home: rauschma.de <http://rauschma.de>
>> twitter: twitter.com/rauschma <http://twitter.com/rauschma>
>> blog: 2ality.com <http://2ality.com>
>>
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>> Oliver Hunt <mailto:oliver at apple.com>
>> September 13, 2013 5:39 PM
>> On Sep 13, 2013, at 9:18 AM, Brendan Eich<brendan at mozilla.com> wrote:
>>
>>>> Oliver Hunt<mailto:oliver at apple.com>
>>>> September 13, 2013 6:11 PM
>>>> Okay so we were discussing among ourselves, and we thought that a 
>>>> sane "desugaring" for
>>>>
>>>> function f(x=expr) {
>>>> ...
>>>> }
>>>>
>>>> would be
>>>>
>>>> function f(x) {
>>>> if (arguments.length< 1) x=expr;
>>>> ...
>>>> }
>>> ES6 has two things that go against this, already in consensus among 
>>> those at the meetings (we miss you shiny fruit-company people ;-):
>> More of the consensus discussion need to happen on es-discuss, this 
>> is the only standards body i'm involved in that seems to require 
>> details be hammered out in F2F meetings. It's one of the things I 
>> find disappointing about the ES standard - the avoidance of 
>> es-discuss when discussing language features makes it actively 
>> difficult for input from the wider dev community.
>>
>>> * You can have default parameters before parameters without defaults.
>> The spec explicitly states that any parameter without a default, but 
>> after another parameter that does have a default assignment 
>> implicitly has a default property of undefined
>>
>>> * You can pass undefined to trigger defaulting -- this is important 
>>> for composition / delegation.
>> No, it's a terrible feature :D i'm unaware of any language that 
>> supports arbitrary ordering of arguments.
>>
>> The elegant solution i saw someone mention was
>>
>> function f({option1, option2, option3} = {option1:default option1, 
>> ...}) { … }
>>
>> That gives you nicely named parameters! (It was this example that 
>> made me start looking at default parameters in the first place)
>>
>>
>>> I think we all agree that new formal parameter syntax gets rid of 
>>> arguments. Yay!
>>
>> If only we could kill it everywhere! My proposal was to simply ban 
>> arguments as an identifier entirely
>>
>>> The real issue that Andreas's proposal addressed was the insanity of 
>>> body declarations hoisting to be in view of default. But it sounds 
>>> like we do not have consensus on whether or not that's crazy.
>>>> This would produce a consistent and easy to follow semantic for 
>>>> default evaluation, it doesn't introduce any new types of scope, 
>>>> nor does it require any new concepts (temporal dead zones, etc) to 
>>>> be learned by a developer who just wants default parameter values.
>>> The hoisting issue still hits your non-consensus actual parameter 
>>> count (arguments.length) thing, though. When reading the function in 
>>> source order, one sees a default expression. Mentally moving the 
>>> defaulting to the body means that hoisted body decls trump outer 
>>> bindings for names in the expression, indeed. But mentally moving is 
>>> the objectionable part -- cognitive load, and non-source-order 
>>> evaluation (more hoisting).
>>>
>>> Hoisting need not perpetuate itself this way. We can do better, or 
>>> at least Andreas proposes that we do. I'm sympathetic.
>>>
>>> Temporal dead zones are indeed weirder but perhaps pay for 
>>> themselves by catching errors. But is it an error to use an outer 
>>> name binding in the default expression, given its position in the 
>>> formal parameter list? I think not.
>>
>> The problem with temporal dead zones is that they lead to weird 
>> behaviour in edge cases, and almost all of them should be 
>> syntactically identifiable as errors up front. The problem is that 
>> you can only _almost_ get syntax checked behaviour upfront because eval.
>>
>>>> We also felt that if you use default or rest parameters we should 
>>>> consider that as a opt out from the magic arguments object, and 
>>>> just poison the arguments identifier entirely (no read, write, or 
>>>> declare)
>>> SpiderMonkey's prototype implementation does this, and I asserted 
>>> above that ES6 specs it. Not so?
>>
>> The ES6 spec (as far as i can read it) only bans declaration of 
>> parameters/vars named "arguments" it doesn't ban reading them.
>>
>>> /be
>>>
>>
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>> Brendan Eich <mailto:brendan at mozilla.com>
>> September 13, 2013 5:18 PM
>>> Oliver Hunt <mailto:oliver at apple.com>
>>> September 13, 2013 6:11 PM
>>> Okay so we were discussing among ourselves, and we thought that a 
>>> sane "desugaring" for
>>>
>>> function f(x=expr) {
>>> ...
>>> }
>>>
>>> would be
>>>
>>> function f(x) {
>>> if (arguments.length < 1) x=expr;
>>> ...
>>> }
>>
>> ES6 has two things that go against this, already in consensus among 
>> those at the meetings (we miss you shiny fruit-company people ;-):
>>
>> * You can have default parameters before parameters without defaults.
>>
>> * You can pass undefined to trigger defaulting -- this is important 
>> for composition / delegation.
>>
>> I think we all agree that new formal parameter syntax gets rid of 
>> arguments. Yay!
>>
>> The real issue that Andreas's proposal addressed was the insanity of 
>> body declarations hoisting to be in view of default. But it sounds 
>> like we do not have consensus on whether or not that's crazy.
>>>
>>> This would produce a consistent and easy to follow semantic for 
>>> default evaluation, it doesn't introduce any new types of scope, nor 
>>> does it require any new concepts (temporal dead zones, etc) to be 
>>> learned by a developer who just wants default parameter values.
>>
>> The hoisting issue still hits your non-consensus actual parameter 
>> count (arguments.length) thing, though. When reading the function in 
>> source order, one sees a default expression. Mentally moving the 
>> defaulting to the body means that hoisted body decls trump outer 
>> bindings for names in the expression, indeed. But mentally moving is 
>> the objectionable part -- cognitive load, and non-source-order 
>> evaluation (more hoisting).
>>
>> Hoisting need not perpetuate itself this way. We can do better, or at 
>> least Andreas proposes that we do. I'm sympathetic.
>>
>> Temporal dead zones are indeed weirder but perhaps pay for themselves 
>> by catching errors. But is it an error to use an outer name binding 
>> in the default expression, given its position in the formal parameter 
>> list? I think not.
>>>
>>> We also felt that if you use default or rest parameters we should 
>>> consider that as a opt out from the magic arguments object, and just 
>>> poison the arguments identifier entirely (no read, write, or declare)
>>
>> SpiderMonkey's prototype implementation does this, and I asserted 
>> above that ES6 specs it. Not so?
>>
>> /be
>>
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>> Oliver Hunt <mailto:oliver at apple.com>
>> September 13, 2013 5:11 PM
>> Okay so we were discussing among ourselves, and we thought that a 
>> sane "desugaring" for
>>
>> function f(x=expr) {
>> ...
>> }
>>
>> would be
>>
>> function f(x) {
>> if (arguments.length < 1) x=expr;
>> ...
>> }
>>
>> This would produce a consistent and easy to follow semantic for 
>> default evaluation, it doesn't introduce any new types of scope, nor 
>> does it require any new concepts (temporal dead zones, etc) to be 
>> learned by a developer who just wants default parameter values.
>>
>> We also felt that if you use default or rest parameters we should 
>> consider that as a opt out from the magic arguments object, and just 
>> poison the arguments identifier entirely (no read, write, or declare)
>>
>> --Oliver
>>
>>
>>
>>
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
> Axel Rauschmayer <mailto:axel at rauschma.de>
> September 13, 2013 6:36 PM
>
> Thanks! I didn’t look at the spec section, I (incorrectly) assumed I 
> knew how they worked. Then I don’t see a use case for this, I’d find 
> it confusing.
>
> -- 
> Dr. Axel Rauschmayer
> axel at rauschma.de <mailto:axel at rauschma.de>
>
> home: rauschma.de <http://rauschma.de>
> twitter: twitter.com/rauschma <http://twitter.com/rauschma>
> blog: 2ality.com <http://2ality.com>
>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
> Tab Atkins Jr. <mailto:jackalmage at gmail.com>
> September 13, 2013 6:10 PM
>
> This doesn't do what you appear to think it does. In particular,
> calling it with "getRandomInteger(5)" is *not* equivalent to calling
> it with "getRandomInteger(0, 5)", it's equivalent to calling it with
> "getRandomInteger(5, undefined)".
>
> This is precisely what the spec section you've quoted says, so I'm not
> sure how you're confused on this point.
>
> ~TJ
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>


More information about the es-discuss mailing list