Function length

classic Classic list List threaded Threaded
24 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Function length

Irakli Gozalishvili
I just noticed strange behavior in spider monkey implementation of rest arguments:

(function(a, b, ...rest) {}).length // => 2

I think ignoring `rest` in length is pretty counter intuitive. For example I have small utility function that
I use to dispatch depending on argument length.

var sum = dispatcher([
  function() { return 0 },
  function(x) { return x },
  function(x, y) { return x + y },
  function(x, y, z) { return Array.prototype.slice.call(arguments, 1).reduce(sum, x) }
]) 

This behavior of rest would obviously break assumptions made by this library. That being said I don't think `3` would be any better. Maybe such functions length should be:

- Infinity ?
- 2.5 ?

That way libraries would be able to handle them in a nice way:

var sum = dispatcher([
  () => 0,
  (x) => x,
  (x, y) => x + y,
  (x, ...rest) => rest.reduce(sum, x)
])


Regards
--
Irakli Gozalishvili
Web: http://www.jeditoolkit.com/


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Function length

Erik Arvidsson

Don't you want to use arguments.length instead of function.length?

On Jun 9, 2012 6:53 PM, "Irakli Gozalishvili" <[hidden email]> wrote:
I just noticed strange behavior in spider monkey implementation of rest arguments:

(function(a, b, ...rest) {}).length // => 2

I think ignoring `rest` in length is pretty counter intuitive. For example I have small utility function that
I use to dispatch depending on argument length.

var sum = dispatcher([
  function() { return 0 },
  function(x) { return x },
  function(x, y) { return x + y },
  function(x, y, z) { return Array.prototype.slice.call(arguments, 1).reduce(sum, x) }
]) 

This behavior of rest would obviously break assumptions made by this library. That being said I don't think `3` would be any better. Maybe such functions length should be:

- Infinity ?
- 2.5 ?

That way libraries would be able to handle them in a nice way:

var sum = dispatcher([
  () => 0,
  (x) => x,
  (x, y) => x + y,
  (x, ...rest) => rest.reduce(sum, x)
])


Regards
--
Irakli Gozalishvili
Web: http://www.jeditoolkit.com/


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Function length

Rick Waldron

On Saturday, June 9, 2012 at 11:53 PM, Erik Arvidsson wrote:

Don't you want to use arguments.length instead of function.length?

On Jun 9, 2012 6:53 PM, "Irakli Gozalishvili" <[hidden email]> wrote:
I just noticed strange behavior in spider monkey implementation of rest arguments:

(function(a, b, ...rest) {}).length // => 2
I agree that this is strange, I would expect 3, as there are three formally named parameters. 

Rick

 

I think ignoring `rest` in length is pretty counter intuitive. For example I have small utility function that
I use to dispatch depending on argument length.

var sum = dispatcher([
  function() { return 0 },
  function(x) { return x },
  function(x, y) { return x + y },
  function(x, y, z) { return Array.prototype.slice.call(arguments, 1).reduce(sum, x) }
]) 

This behavior of rest would obviously break assumptions made by this library. That being said I don't think `3` would be any better. Maybe such functions length should be:

- Infinity ?
- 2.5 ?

That way libraries would be able to handle them in a nice way:

var sum = dispatcher([
  () => 0,
  (x) => x,
  (x, y) => x + y,
  (x, ...rest) => rest.reduce(sum, x)
])


Regards
--
Irakli Gozalishvili
Web: http://www.jeditoolkit.com/


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
https://mail.mozilla.org/listinfo/es-discuss


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Function length

Erik Arvidsson
On Sat, Jun 9, 2012 at 9:08 PM, Rick Waldron <[hidden email]> wrote:
> I just noticed strange behavior in spider monkey implementation of rest
> arguments:
>
> (function(a, b, ...rest) {}).length // => 2
>
> I agree that this is strange, I would expect 3, as there are three formally
> named parameters.

The length in ES5 is not very consistent.

For ES6 we decide that we wanted the function length to be used to
tell how many required parameters a function has.

Today rest params are done using arguments:

(function(a, b) {
  var rest = Array.prototype.slice.call(arguments, 2);
}).length  // => 2

The rule is that optional and rest parameters are not included in the
length of the function.

--
erik
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Function length

Allen Wirfs-Brock
In reply to this post by Irakli Gozalishvili

On Jun 9, 2012, at 6:52 PM, Irakli Gozalishvili wrote:

I just noticed strange behavior in spider monkey implementation of rest arguments:

(function(a, b, ...rest) {}).length // => 2


That answer is consistent with what is specified in the ES6 draft spec.  The actual value is specified algorithmically  and is summarized by this note:

NOTE The ExpectedArgumentCount of a FormalParameterList is the number of FormalParameters to the left of either the rest parameter or the first FormalParameter with an Initialiser. A FormalParameter without an initializer are allowed after the first parameter with an initializer but such parameters are considered to be optional with undefined as their default value.


See section 13.1.

The draft is based upon the conclusions that were reached when this was last discussed.  See the thread starting https://mail.mozilla.org/pipermail/es-discuss/2011-August/016361.html 

There is no obviously "right" answer to what should be reported as the length (and it isn't clear whether this property really has any utility).  The closest thing we have to legacy precedent are these statement from previous versions of the spec:

15 Every built-in Function object described in this clause—whether as a constructor, an ordinary function, or both—has a length property whose value is an integer. Unless otherwise specified, this value is equal to the largest number of named arguments shown in the subclause headings for the function description, including optional parameters.

15.3.5.1 The value of the length property is an integer that indicates the “typical” number of arguments expected by the function.

Note that that the the legacy description is not particularly self consistent and that where a length value is "other specified" for various built-in functions it tends to follow the 15.3.5.1 rule.

Allen




_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Function length

Irakli Gozalishvili
Never the less problem still stands, but maybe there are other ways to solve it. Only solution I'm left with so far is utility function like this:

function hasRest(f) {
  return !!~String(f).split('\n').shift().indexOf('...')
}

Which is bad, specially toString of function is not guaranteed to return source.

Maybe alternative solution could be some standard function / method to test if the function captures ...rest args.

Regards
--
Irakli Gozalishvili
Web: http://www.jeditoolkit.com/

On Saturday, 2012-06-09 at 23:54 , Allen Wirfs-Brock wrote:


On Jun 9, 2012, at 6:52 PM, Irakli Gozalishvili wrote:

I just noticed strange behavior in spider monkey implementation of rest arguments:

(function(a, b, ...rest) {}).length // => 2


That answer is consistent with what is specified in the ES6 draft spec.  The actual value is specified algorithmically  and is summarized by this note:

NOTE The ExpectedArgumentCount of a FormalParameterList is the number of FormalParameters to the left of either the rest parameter or the first FormalParameter with an Initialiser. A FormalParameter without an initializer are allowed after the first parameter with an initializer but such parameters are considered to be optional with undefined as their default value.


See section 13.1.

The draft is based upon the conclusions that were reached when this was last discussed.  See the thread starting https://mail.mozilla.org/pipermail/es-discuss/2011-August/016361.html 

There is no obviously "right" answer to what should be reported as the length (and it isn't clear whether this property really has any utility).  The closest thing we have to legacy precedent are these statement from previous versions of the spec:

15 Every built-in Function object described in this clause—whether as a constructor, an ordinary function, or both—has a length property whose value is an integer. Unless otherwise specified, this value is equal to the largest number of named arguments shown in the subclause headings for the function description, including optional parameters.

15.3.5.1 The value of the length property is an integer that indicates the “typical” number of arguments expected by the function.

Note that that the the legacy description is not particularly self consistent and that where a length value is "other specified" for various built-in functions it tends to follow the 15.3.5.1 rule.

Allen





_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Function length

John Tamplin
On Sun, Jun 10, 2012 at 12:48 PM, Irakli Gozalishvili <[hidden email]> wrote:
Never the less problem still stands, but maybe there are other ways to solve it. Only solution I'm left with so far is utility function like this:

function hasRest(f) {
  return !!~String(f).split('\n').shift().indexOf('...')
}

Which is bad, specially toString of function is not guaranteed to return source.

Maybe alternative solution could be some standard function / method to test if the function captures ...rest args.

You could imagine a method like Function.prototype.hasRestArgs, but that wouldn't catch the existing varargs-style coding based on arguments.

--
John A. Tamplin
Software Engineer (GWT), Google

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Function length

Andreas Rossberg-4
In reply to this post by Irakli Gozalishvili
On 10 June 2012 03:52, Irakli Gozalishvili <[hidden email]> wrote:

> I just noticed strange behavior in spider monkey implementation of rest
> arguments:
>
> (function(a, b, ...rest) {}).length // => 2
>
> I think ignoring `rest` in length is pretty counter intuitive. For example I
> have small utility function that
> I use to dispatch depending on argument length.
>
> var sum = dispatcher([
>   function() { return 0 },
>   function(x) { return x },
>   function(x, y) { return x + y },
>   function(x, y, z) { return Array.prototype.slice.call(arguments,
> 1).reduce(sum, x) }
> ])

I don't think any library should ever rely on f.length. It is not a
reliable source of information (f might use 'arguments' even when the
length is officially 0), and I don't honestly see it being useful for
anything but tertiary debugging purposes.

/Andreas
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Function length

Irakli Gozalishvili
I don't think any library should ever rely on f.length. 

That's a wrong  attitude, there always will be legitimate uses of any feature, otherwise such features are just harmful & IMO should  be deprecated / removed. 

It is not a
reliable source of information (f might use 'arguments' even when the
length is officially 0), and I don't honestly see it being useful for
anything but tertiary debugging purposes.

In some cases weather function captures `rest` arguments via `arguments` is irrelevant. Like in a case I've pointed out earlier. Library provides arity based dispatch based on f.length, so if you pass `function() { arguments…. }` it will never be called with more than 0 arguments.

Regards
--
Irakli Gozalishvili
Web: http://www.jeditoolkit.com/

On Monday, 2012-06-11 at 05:33 , Andreas Rossberg wrote:

On 10 June 2012 03:52, Irakli Gozalishvili <[hidden email]> wrote:
I just noticed strange behavior in spider monkey implementation of rest
arguments:

(function(a, b, ...rest) {}).length // => 2

I think ignoring `rest` in length is pretty counter intuitive. For example I
have small utility function that
I use to dispatch depending on argument length.

var sum = dispatcher([
  function() { return 0 },
  function(x) { return x },
  function(x, y) { return x + y },
  function(x, y, z) { return Array.prototype.slice.call(arguments,
1).reduce(sum, x) }
])

I don't think any library should ever rely on f.length. It is not a
reliable source of information (f might use 'arguments' even when the
length is officially 0), and I don't honestly see it being useful for
anything but tertiary debugging purposes.

/Andreas


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Function length

Allen Wirfs-Brock

On Jun 11, 2012, at 10:56 AM, Irakli Gozalishvili wrote:

I don't think any library should ever rely on f.length. 

That's a wrong  attitude, there always will be legitimate uses of any feature, otherwise such features are just harmful & IMO should  be deprecated / removed. 

Let me try again.  We don't understand your use case.  You didn't show us the definition of your dispatch function so we have to guess.  Even so, It is hard to imagine a "legitimate" use with dynamically provided functions, particularly as the length values assigned to the existing built-ins don't follow strict rules. At the very least you need to help us understand why your use case is both reasonable and valid.

Allen




_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Function length

Brendan Eich-2
In reply to this post by Irakli Gozalishvili
I would not mind removing Function 'length' but on the web you cannot
deprecate and any browser daring to remove will appear broken to users
not involved in the content or the engine, and users switch browsers.

Anyway, back to reality: foo.length is in ECMA-262 and we need to spec
how it works in the presence of a trailing rest parameter. Allen has
drafted something based on discussion here. It's a plausible design and
hard to criticize without both your use-case (in detail) and a better
alternative.

/be

Irakli Gozalishvili wrote:

>> I don't think any library should ever rely on f.length.
>
> That's a wrong  attitude, there always will be legitimate uses of any
> feature, otherwise such features are just harmful & IMO should  be
> deprecated / removed.
>
>> It is not a
>> reliable source of information (f might use 'arguments' even when the
>> length is officially 0), and I don't honestly see it being useful for
>> anything but tertiary debugging purposes.
>
> In some cases weather function captures `rest` arguments via
> `arguments` is irrelevant. Like in a case I've pointed out earlier.
> Library provides arity based dispatch based on f.length, so if you
> pass `function() { arguments…. }` it will never be called with more
> than 0 arguments.
>
> Regards
> --
> Irakli Gozalishvili
> Web: http://www.jeditoolkit.com/
>
> On Monday, 2012-06-11 at 05:33 , Andreas Rossberg wrote:
>
>> On 10 June 2012 03:52, Irakli Gozalishvili <[hidden email]
>> <mailto:[hidden email]>> wrote:
>>> I just noticed strange behavior in spider monkey implementation of rest
>>> arguments:
>>>
>>> (function(a, b, ...rest) {}).length // => 2
>>>
>>> I think ignoring `rest` in length is pretty counter intuitive. For
>>> example I
>>> have small utility function that
>>> I use to dispatch depending on argument length.
>>>
>>> var sum = dispatcher([
>>>   function() { return 0 },
>>>   function(x) { return x },
>>>   function(x, y) { return x + y },
>>>   function(x, y, z) { return Array.prototype.slice.call(arguments,
>>> 1).reduce(sum, x) }
>>> ])
>>
>> I don't think any library should ever rely on f.length. It is not a
>> reliable source of information (f might use 'arguments' even when the
>> length is officially 0), and I don't honestly see it being useful for
>> anything but tertiary debugging purposes.
>>
>> /Andreas
>
> _______________________________________________
> es-discuss mailing list
> [hidden email]
> https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Function length

Irakli Gozalishvili
In reply to this post by Allen Wirfs-Brock
Sorry for not being clear about this. Here is a simplified example of the implementation:
https://gist.github.com/2911817

Also this is just a single particular example, but I expect there to be more. I think what I'm
really asking for is a way to know if …rest is being used.

Also IMO arrow functions should not have `arguments` at all.  

Regards
--
Irakli Gozalishvili
Web: http://www.jeditoolkit.com/

On Monday, 2012-06-11 at 11:04 , Allen Wirfs-Brock wrote:


On Jun 11, 2012, at 10:56 AM, Irakli Gozalishvili wrote:

I don't think any library should ever rely on f.length. 

That's a wrong  attitude, there always will be legitimate uses of any feature, otherwise such features are just harmful & IMO should  be deprecated / removed. 

Let me try again.  We don't understand your use case.  You didn't show us the definition of your dispatch function so we have to guess.  Even so, It is hard to imagine a "legitimate" use with dynamically provided functions, particularly as the length values assigned to the existing built-ins don't follow strict rules. At the very least you need to help us understand why your use case is both reasonable and valid.

Allen





_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Function length

medikoo
In reply to this post by Brendan Eich-2
I find Function 'length' as very useful property (I use it in some low-level functional stuff). I also think that defining functions so it reflects only required arguments is very sane decision. In that light I would also expect ...rest to not be counted in Function length.

+1 for keeping it, the way it is.

Brendan Eich-2 wrote
I would not mind removing Function 'length' but on the web you cannot
deprecate and any browser daring to remove will appear broken to users
not involved in the content or the engine, and users switch browsers.

Anyway, back to reality: foo.length is in ECMA-262 and we need to spec
how it works in the presence of a trailing rest parameter. Allen has
drafted something based on discussion here. It's a plausible design and
hard to criticize without both your use-case (in detail) and a better
alternative.

/be

Irakli Gozalishvili wrote:
>> I don't think any library should ever rely on f.length.
>
> That's a wrong  attitude, there always will be legitimate uses of any
> feature, otherwise such features are just harmful & IMO should  be
> deprecated / removed.
>
>> It is not a
>> reliable source of information (f might use 'arguments' even when the
>> length is officially 0), and I don't honestly see it being useful for
>> anything but tertiary debugging purposes.
>
> In some cases weather function captures `rest` arguments via
> `arguments` is irrelevant. Like in a case I've pointed out earlier.
> Library provides arity based dispatch based on f.length, so if you
> pass `function() { arguments…. }` it will never be called with more
> than 0 arguments.
>
> Regards
> --
> Irakli Gozalishvili
> Web: http://www.jeditoolkit.com/
>
> On Monday, 2012-06-11 at 05:33 , Andreas Rossberg wrote:
>
>> On 10 June 2012 03:52, Irakli Gozalishvili <rfobic@gmail.com
>> <mailto:rfobic@gmail.com>> wrote:
>>> I just noticed strange behavior in spider monkey implementation of rest
>>> arguments:
>>>
>>> (function(a, b, ...rest) {}).length // => 2
>>>
>>> I think ignoring `rest` in length is pretty counter intuitive. For
>>> example I
>>> have small utility function that
>>> I use to dispatch depending on argument length.
>>>
>>> var sum = dispatcher([
>>>   function() { return 0 },
>>>   function(x) { return x },
>>>   function(x, y) { return x + y },
>>>   function(x, y, z) { return Array.prototype.slice.call(arguments,
>>> 1).reduce(sum, x) }
>>> ])
>>
>> I don't think any library should ever rely on f.length. It is not a
>> reliable source of information (f might use 'arguments' even when the
>> length is officially 0), and I don't honestly see it being useful for
>> anything but tertiary debugging purposes.
>>
>> /Andreas
>
> _______________________________________________
> 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
Reply | Threaded
Open this post in threaded view
|

Re: Function length

Brendan Eich-2
In reply to this post by Irakli Gozalishvili
Irakli Gozalishvili wrote:
> Sorry for not being clear about this. Here is a simplified example of
> the implementation:
> https://gist.github.com/2911817
>
> Also this is just a single particular example, but I expect there to
> be more. I think what I'm
> really asking for is a way to know if …rest is being used.

Your code doesn't work on a function that uses arguments the old
fashioned way, though.

Yes, you can make ...rest affect .length and make a dispatcher that
counts on that, but it's a just-so story and a hard case. Hard cases
make bad law. If it really matters, we can provide better reflection
facilities, but I'm pretty sure it doesn't occur enough to justify doing
so now.

So use the toString hack if you must and let's see if this use-case
becomes hot.

> Also IMO arrow functions should not have `arguments` at all.

That's already in the proposal:

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

"The /Identifier/ primary expression |arguments| may not be used in an
arrow function’s body (whether expression or block form)."

/be

>
> Regards
> --
> Irakli Gozalishvili
> Web: http://www.jeditoolkit.com/
>
> On Monday, 2012-06-11 at 11:04 , Allen Wirfs-Brock wrote:
>
>>
>> On Jun 11, 2012, at 10:56 AM, Irakli Gozalishvili wrote:
>>
>>>> I don't think any library should ever rely on f.length.
>>>
>>> That's a wrong  attitude, there always will be legitimate uses of
>>> any feature, otherwise such features are just harmful & IMO should
>>>  be deprecated / removed.
>>
>> Let me try again.  We don't understand your use case.  You didn't
>> show us the definition of your dispatch function so we have to guess.
>>  Even so, It is hard to imagine a "legitimate" use with dynamically
>> provided functions, particularly as the length values assigned to the
>> existing built-ins don't follow strict rules. At the very least you
>> need to help us understand why your use case is both reasonable and
>> valid.
>>
>> Allen
>>
>>
>>
>
> _______________________________________________
> es-discuss mailing list
> [hidden email]
> https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Function length

Felix Böhm
The big question is whether Function#length should represent minimum or the maximum amount of arguments. That means that a rest parameter could have zero elements, and optional parameters could fall back to their default value. The minimum approach wouldn't count them, the maximum would expect the most and return positive infinity as soon as the rest parameter is available.

Both approaches have their right to exist. With the maximum approach, the length property could even become a setter: By setting it, the values always default to the defined value, and rest parameters have a maximum length. 

It would be nice to get both getters.

(Brendan, I'm sorry for sending you this message twice.)

2012/6/11 Brendan Eich <[hidden email]>
Irakli Gozalishvili wrote:
Sorry for not being clear about this. Here is a simplified example of the implementation:
https://gist.github.com/2911817

Also this is just a single particular example, but I expect there to be more. I think what I'm
really asking for is a way to know if …rest is being used.

Your code doesn't work on a function that uses arguments the old fashioned way, though.

Yes, you can make ...rest affect .length and make a dispatcher that counts on that, but it's a just-so story and a hard case. Hard cases make bad law. If it really matters, we can provide better reflection facilities, but I'm pretty sure it doesn't occur enough to justify doing so now.

So use the toString hack if you must and let's see if this use-case becomes hot.


Also IMO arrow functions should not have `arguments` at all.

That's already in the proposal:

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

"The /Identifier/ primary expression |arguments| may not be used in an arrow function’s body (whether expression or block form)."

/be


Regards
--
Irakli Gozalishvili
Web: http://www.jeditoolkit.com/

On Monday, 2012-06-11 at 11:04 , Allen Wirfs-Brock wrote:


On Jun 11, 2012, at 10:56 AM, Irakli Gozalishvili wrote:

I don't think any library should ever rely on f.length.

That's a wrong  attitude, there always will be legitimate uses of any feature, otherwise such features are just harmful & IMO should  be deprecated / removed.

Let me try again.  We don't understand your use case.  You didn't show us the definition of your dispatch function so we have to guess.  Even so, It is hard to imagine a "legitimate" use with dynamically provided functions, particularly as the length values assigned to the existing built-ins don't follow strict rules. At the very least you need to help us understand why your use case is both reasonable and valid.

Allen




_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Function length

Russell Leggett
In reply to this post by Brendan Eich-2
On Mon, Jun 11, 2012 at 3:50 PM, Brendan Eich <[hidden email]> wrote:
Irakli Gozalishvili wrote:
Sorry for not being clear about this. Here is a simplified example of the implementation:
https://gist.github.com/2911817

Also this is just a single particular example, but I expect there to be more. I think what I'm
really asking for is a way to know if …rest is being used.

Your code doesn't work on a function that uses arguments the old fashioned way, though.

Yes, you can make ...rest affect .length and make a dispatcher that counts on that, but it's a just-so story and a hard case. Hard cases make bad law. If it really matters, we can provide better reflection facilities, but I'm pretty sure it doesn't occur enough to justify doing so now.

So use the toString hack if you must and let's see if this use-case becomes hot.

I think this is a pretty creative snippet of code, but ultimately unreliable for the reasons mentioned. It does bring up something else, though, that I've avoided mentioning so far, which is pattern matching. I haven't mentioned it because there is clearly a strawman for it, and that never made it to harmony, but in light of this thread I wanted to reiterate how useful it would be. It would not really help function.length, but would address the real underlying problem that the arity dispatcher is trying to tackle. In a language without overloading, the ability to do pattern matching would be an excellent solution to a very common problem. We already have destructuring, it seems like such a small jump to pattern matching. Hard to tell from looking at the strawman why that never made it. If its a matter or feature bloat, I would rate that higher than some other things like default args or array comprehensions.

- Russ

- Russ

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Function length

Brendan Eich-2
Russell Leggett wrote:

> It does bring up something else, though, that I've avoided mentioning
> so far, which is pattern matching. I haven't mentioned it because
> there is clearly a strawman
> <http://wiki.ecmascript.org/doku.php?id=strawman:pattern_matching> for
> it, and that never made it to harmony, but in light of this thread I
> wanted to reiterate how useful it would be. It would not really help
> function.length, but would address the real underlying problem that
> the arity dispatcher is trying to tackle. In a language without
> overloading, the ability to do pattern matching would be an excellent
> solution to a very common problem. We already have destructuring, it
> seems like such a small jump to pattern matching.

You are preacher, dherman and I are choir. Maybe patterns will make ES7.
We shall try again.

> Hard to tell from looking at the strawman why that never made it. If
> its a matter or feature bloat, I would rate that higher than some
> other things like default args or array comprehensions.

See March 2011 TC39 meeting notes, second day.

Quotes below. Note some fine specimens of TC39's future-proofing
fetishization on parade. I will say no more, as I think Dave agrees
patterns were not fully baked.

The way to get refutable matching into ES7 is to work now to address all
the valid worries, and say why the other worries are false.

/be

[From https://mail.mozilla.org/pipermail/es-discuss/2011-March/013403.html]

Refutable matching and switch extensions:
Multiple objections to syntax chosen for pattern-matching switch:
colon vs. no colon after default clause, need for blocks, etc.
Refutable matching doesn't retrofit into imperative switch syntax
well.
Waldemar: Refutable matching is half-baked at this point, with too
many syntactic and semantic problems.  Not clear it's worth its added
complexity.

The refutable matching wiki has the following consequences on
irrefutable matching:
Pattern [x,y]:
Matched to [3,4], produces x=3, y=4.
Matched to [3,4,5], produces x=3, y=4.
Matched to [3], produces x=undefined, y=undefined.  (wiki spec bug.)
Pattern [..., x, y]:
Matched to [3,4], produces x=3, y=4.
Matched to [3], looks up negative array indices.  (wiki spec bug.)

Pattern [x,y] behaves like [x,y,...] for refutable matching.  (wiki spec bug.)
Can't match on zero-length arrays. (wiki spec bug?)

Lucas: Feature value should overcome complexity costs.
Waldemar: if guards introduce unknown syntactic and semantic complexity
Waldemar: where can you use refutable matching outside of switch/match
statements and perhaps catch guards?  switch/match statements are too
heavyweight and differ too much from irrefutable matching assignment;
catching doesn't really need destructuring but benefits from
conditions.  The typical usage (as in Perl) is to use them in if
statements:  if (pattern =~ expr) {we have matched!}

catch({z,w} if z<  w):  OK, but then you can't get to the entire
exception object from the catch clause.
catch(z if z instanceof T):  Useful

Waldemar: Refutable matching should integrate trademarking to be compelling.
Concern about backing ourselves into a corner by implementing
irrefutable pattern matching in catch guards that will later preclude
refutable matching.  Brendan's example:  catch({x, y}) would succeed
on {x:3} now but fail later if we change to refutable pattern
matching.


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Function length

Russell Leggett
On Tue, Jun 12, 2012 at 1:06 PM, Brendan Eich <[hidden email]> wrote:
Russell Leggett wrote:
It does bring up something else, though, that I've avoided mentioning so far, which is pattern matching. I haven't mentioned it because there is clearly a strawman <http://wiki.ecmascript.org/doku.php?id=strawman:pattern_matching> for it, and that never made it to harmony, but in light of this thread I wanted to reiterate how useful it would be. It would not really help function.length, but would address the real underlying problem that the arity dispatcher is trying to tackle. In a language without overloading, the ability to do pattern matching would be an excellent solution to a very common problem. We already have destructuring, it seems like such a small jump to pattern matching.

You are preacher, dherman and I are choir. Maybe patterns will make ES7. We shall try again.


Hard to tell from looking at the strawman why that never made it. If its a matter or feature bloat, I would rate that higher than some other things like default args or array comprehensions.

See March 2011 TC39 meeting notes, second day.

Quotes below. Note some fine specimens of TC39's future-proofing fetishization on parade. I will say no more, as I think Dave agrees patterns were not fully baked.

The way to get refutable matching into ES7 is to work now to address all the valid worries, and say why the other worries are false.

This thread gave me an interesting idea on how to possibly attack pattern matching in ES6 with no new syntax, and still leave room for more sugar later. It actually comes from thinking about the original issue with function.length and using it for arity-based dispatch. What if we just gave a better method than length? What if we had something like function.matches(args)? Where it would return true if all arguments were bound, and no parameters resulted in an undefined binding.
    function add(a,b){
        return a + b;
    }

    add.matches(1,2); // => true
    add.matches(1); // => false
    add.matches(1,2,3);  => false

This still suffers from the same problem as function.length, and when dealing with simple arity and no destructuring/rest params, would act exactly the same. However, Irakli's dispatcher utility does lay the groundwork for something more interesting.

    function makePoint(x,y){ return {x:x,y:y}; }
    function drawLine({x:x1,y:y1},{x:x2,y:y2}){...}

    let p1 = makePoint(1,2), p2 = makePoint(3,4);    
    drawLine.matches(p1,p2); // => true
    drawLine.matches(1,2); // => false
    drawLine.matches({x:1}, {y:2}) // => false
    //only has to be a structural subset
    drawLine.matches({x:1,y:2,z:3}, {x:1, y:2}) // => true
    
With that simple boolean function, Irakli's dispatcher utility could be rewritten to loop through the list and check for a match instead of by arity. It would work correctly for rest parameters, but even more interesting, would work with all of the destructuring patterns.

    let drawLine = dispatcher(
        (x1,y1,x2,y2) => ...,
        ({x:x1,y:y1},{x:x2,y:y2}) => ...
    );
    
Or a more functional replacement for switch

    let result = match(value, 
        ({x,y,z}) => "3d"
        ({x,y}) => "2d"
        (...anything) => "not a point"
    );
    
Its not as nice as full pattern matching with literals and wildcards, but it could be pretty clean. If guards were added later, that would be an obvious fit. If it became a popular pattern, we could pave the cowpath with some sugar, and add the things that are missing now.

One of the benefits of getting started this way is that it could be shimmed to just use length.


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Function length

Tom Ellis-3
I like the look of this:

    function add(a,b){
        return a + b;
    }

    add.matches(1,2); // => true
    add.matches(1); // => false
    add.matches(1,2,3);  => false


I've never had the need to use function.length, I probably will at some point though.

If you did something like this, using the rest argument:

function add( a, b, ...others ) {
    ...
}

Then the following should occur:

add.matches(1,2) // => true
add.matches(1) //=> false
add.matches(1,3,4) //=> true

Tom


On 12 Jun 2012, at 22:57, Russell Leggett wrote:

On Tue, Jun 12, 2012 at 1:06 PM, Brendan Eich <[hidden email]> wrote:
Russell Leggett wrote:
It does bring up something else, though, that I've avoided mentioning so far, which is pattern matching. I haven't mentioned it because there is clearly a strawman <http://wiki.ecmascript.org/doku.php?id=strawman:pattern_matching> for it, and that never made it to harmony, but in light of this thread I wanted to reiterate how useful it would be. It would not really help function.length, but would address the real underlying problem that the arity dispatcher is trying to tackle. In a language without overloading, the ability to do pattern matching would be an excellent solution to a very common problem. We already have destructuring, it seems like such a small jump to pattern matching.

You are preacher, dherman and I are choir. Maybe patterns will make ES7. We shall try again.


Hard to tell from looking at the strawman why that never made it. If its a matter or feature bloat, I would rate that higher than some other things like default args or array comprehensions.

See March 2011 TC39 meeting notes, second day.

Quotes below. Note some fine specimens of TC39's future-proofing fetishization on parade. I will say no more, as I think Dave agrees patterns were not fully baked.

The way to get refutable matching into ES7 is to work now to address all the valid worries, and say why the other worries are false.

This thread gave me an interesting idea on how to possibly attack pattern matching in ES6 with no new syntax, and still leave room for more sugar later. It actually comes from thinking about the original issue with function.length and using it for arity-based dispatch. What if we just gave a better method than length? What if we had something like function.matches(args)? Where it would return true if all arguments were bound, and no parameters resulted in an undefined binding.
    function add(a,b){
        return a + b;
    }

    add.matches(1,2); // => true
    add.matches(1); // => false
    add.matches(1,2,3);  => false

This still suffers from the same problem as function.length, and when dealing with simple arity and no destructuring/rest params, would act exactly the same. However, Irakli's dispatcher utility does lay the groundwork for something more interesting.

    function makePoint(x,y){ return {x:x,y:y}; }
    function drawLine({x:x1,y:y1},{x:x2,y:y2}){...}

    let p1 = makePoint(1,2), p2 = makePoint(3,4);    
    drawLine.matches(p1,p2); // => true
    drawLine.matches(1,2); // => false
    drawLine.matches({x:1}, {y:2}) // => false
    //only has to be a structural subset
    drawLine.matches({x:1,y:2,z:3}, {x:1, y:2}) // => true
    
With that simple boolean function, Irakli's dispatcher utility could be rewritten to loop through the list and check for a match instead of by arity. It would work correctly for rest parameters, but even more interesting, would work with all of the destructuring patterns.

    let drawLine = dispatcher(
        (x1,y1,x2,y2) => ...,
        ({x:x1,y:y1},{x:x2,y:y2}) => ...
    );
    
Or a more functional replacement for switch

    let result = match(value, 
        ({x,y,z}) => "3d"
        ({x,y}) => "2d"
        (...anything) => "not a point"
    );
    
Its not as nice as full pattern matching with literals and wildcards, but it could be pretty clean. If guards were added later, that would be an obvious fit. If it became a popular pattern, we could pave the cowpath with some sugar, and add the things that are missing now.

One of the benefits of getting started this way is that it could be shimmed to just use length.

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Function length

Andreas Rossberg-4
In reply to this post by Russell Leggett
On 12 June 2012 23:57, Russell Leggett <[hidden email]> wrote:

> This thread gave me an interesting idea on how to possibly attack pattern
> matching in ES6 with no new syntax, and still leave room for more sugar
> later. It actually comes from thinking about the original issue with
> function.length and using it for arity-based dispatch. What if we just gave
> a better method than length? What if we had something like
> function.matches(args)? Where it would return true if all arguments were
> bound, and no parameters resulted in an undefined binding.
>     function add(a,b){
>         return a + b;
>     }
>
>     add.matches(1,2); // => true
>     add.matches(1); // => false
>     add.matches(1,2,3);  => false

OK, I'll bite. I see lots of problems and unnecessary complexity here.

If I understand this correctly, then it will require every function
closure to include meta information for performing the associated
pattern match. Or, when you actually want this to be optimised, the
ability to generate (probably lazily) and attach pattern matching code
to _every_ function closure. That seems pretty intrusive.

Also, the programmer would have to create a closure for every match
arm you ever want to use (unless the compiler is "sufficiently clever"
to recognise rather non-trivial patterns, which I doubt). That is
likely to be pretty costly. I'm also not sure how you envision
actually binding variables during a match. Are you suggesting that one
does something like:

  if (f.matches(x, y)) f(x, y)

Even if this is abstracted into some 'match' function, a match would
redundantly decompose x, y for f twice.

And just to be clear, this feature also reveals implementation details
of a function that it shouldn't. For example, it allows you to observe
cases where a function ignores some of its documented arguments, or
some parts of its arguments. So it has all the bad properties of the
'isBound' function we discussed earlier.

I'd say (despite being part of the pattern matching choir) that this
is not the proper way to introduce a feature that, as a proper
language construct, would be relatively simple, efficient, and
independent of anything else.

/Andreas
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
12