Argument matching

# Michael O'Brien (17 years ago)

What should ES4 do when there are too many or too few arguments?

Seems that the RI will apply different behavior depending on whether
the function arguments are typed or not. This is not necessarily
unexpected. I just want to nail down the rules as the RI and AS3
behave differently in this regard.

Consider:

function fun(a, b) { print(a); print(b); }

Calling this with:

fun(1) prints 1 undefined

fun(1,2,3,4) prints 1 2

fun(1,undefined) 1 0

both work without error.

But if either arg is typed:

function fun(a: int, b) { print(a); print(b); }

In this case, the following all get TypeErrors

fun(1) fun(1, undefined) fun(1,2,3,4)

Interestingly, ASC will coerce "undefined" to 0 if supplied with the
correct number of arguments and they are typed as ints.

What are the rules for ES4?

  • If you type formal arguments, it seems the caller must supply the
    correct number and type of actual parameters
  • If you don't type the formal arguments, you can supply too few or
    too many arguments
  • Should undefined be coerced to 0 if the type is an integer?

Michael

# Lars Hansen (17 years ago)

In strict code ("use strict") the number of passed arguments must match the number of expected arguments. This has been agreed upon.

I would expect that if too few arguments are passed to a function with a typed interface then you get a type error unless the missing parameter has a type that includes "undefined" (ie no conversion takes place). Signalling an error "because the function has a typed interface" is a variant, I guess, but it seems like an orthogonal concern.

I would expect excess arguments to typed functions to be ignored silently, as they can be picked up by 'arguments' inside the function.

# David Mandelin (17 years ago)

Lars Hansen wrote:

I would expect excess arguments to typed functions to be ignored silently, as they can be picked up by 'arguments' inside the function.

Is there any possibility of making whether a function takes extra arguments part of its type? It seems kind of unfortunate not to be able to report an error when too many args are given, which is a pretty common mistake and usually indicates a bug.

# Michael O'Brien (17 years ago)

There is a problem with that.

If it is an error to provide too many actual parameters to a function
with typed formal parameters, then you either must supply the correct
number of args or not type the args.

A use case that demonstrates the problem is the Array.some callback.
Usually it is supplied with only one argument -- the element. So if a
user declares this callback with type annotations, the call will fail
as the iterator must supply 3 arguments.

So you can't have a callback with just one typed argument for the
callback. You must either have one untyped arg or 3 typed arguments.

Michael

# Michael O'Brien (17 years ago)

Comments below: On May 9, 2008, at 10:43 AM, Lars Hansen wrote:

In strict code ("use strict") the number of passed arguments must
match the number of expected arguments. This has been agreed upon.

I presume that is at execution time?

I would expect that if too few arguments are passed to a function with a typed interface then you get a type error unless the missing
parameter has a type that includes "undefined" (ie no conversion takes place).

See comment in following email about Array.some callbacks.

Signalling an error "because the function has a typed interface" is a variant, I guess, but it seems like an orthogonal concern.

I would expect excess arguments to typed functions to be ignored silently, as they can be picked up by 'arguments' inside the function.

I think this is the only approach that will work for standard mode code.

So for Array.some in strict mode, the user must supply 3 typed
arguments for the callback. But in standard mode, they can either do that, or supply one untyped
arg.

I can't think of a better solution (yet).

Michael

# Michael O'Brien (17 years ago)

The tests below in the RI were in standard mode. So that is an RI bug.

Michael

# Lars Hansen (17 years ago)

There are optional and rest arguments in ES4.

Regarding error reporting, strict mode is what gives you sane error checking (generally at run-time). Standard mode is for all you cowboys out there.

# Lars Hansen (17 years ago)

-----Original Message----- From: Michael O'Brien [mailto:mob at mbedthis.com] Sent: 9. mai 2008 11:09 To: Lars Hansen Cc: es4-discuss Discuss Subject: Re: Argument matching

Comments below: On May 9, 2008, at 10:43 AM, Lars Hansen wrote:

In strict code ("use strict") the number of passed arguments must match the number of expected arguments. This has been agreed upon.

I presume that is at execution time?

It is.

So for Array.some in strict mode, the user must supply 3 typed

arguments

for the callback. But in standard mode, they can either do that, or

supply

one untyped arg.

static function some(object:!Object, checker:Callable, thisObj:Object=null): boolean { for (let i=0, limit=object.length; i < limit ; i++) if (i in object) if (checker.call(thisObj, object[i], i, object)) return true; return false; }

The type of 'checker' used to be Checker:

type Checker = function (*, double, Object):boolean;

but that is painful in practice. The intrinsic instance method still requires a Checker, though.

Presumably what you're getting at is that if 'checker' is strict then it must accept three arguments even if we only care about one. This is so. The easiest way to write down a function like that is to use the rest parameter without a parameter name:

function f(obj, ...) { /* code here */ }

# Michael O'Brien (17 years ago)

Presumably what you're getting at is that if 'checker' is strict
then it must accept three arguments even if we only care about one. This is
so. The easiest way to write down a function like that is to use the rest parameter without a parameter name:

function f(obj, ...) { /* code here */ }

Agree, but that may have a performance penalty as the extra args must
be converted to an array. One case where strict mode may be faster
than standard ;-)

So that I can write up a bug for the RI, my take on the rules is:

  • In strict mode, the number and types of args must agree. If not, an
    error is generated.

  • In standard mode, you can supply too many actual parameters, they
    will be ignored. If you supply too few, undefined will be
    automatically supplied for the missing args.

The RI exhibits strict behavior in this regard in standard mode.

Michael

# Lars Hansen (17 years ago)

-----Original Message----- From: Michael O'Brien [mailto:mob at mbedthis.com] Sent: 9. mai 2008 11:49 To: Lars Hansen Cc: es4-discuss Discuss Subject: Re: Argument matching

Presumably what you're getting at is that if 'checker' is strict then it must accept three arguments even if we only care about one. This is so. The easiest way to write down a function like that is to use the rest parameter without a parameter name:

function f(obj, ...) { /* code here */ }

Agree, but that may have a performance penalty as the extra args must be converted to an array.

Why would they have to be converted to an array, if that array can't be referenced? :)

One case where strict mode may be faster than standard ;-)

So that I can write up a bug for the RI, my take on the rules is:

  • In strict mode, the number and types of args must agree. If not, an error is generated.

  • In standard mode, you can supply too many actual parameters, they will be ignored. If you supply too few, undefined will be automatically supplied for the missing args.

In my opinion, yes. But this has not been discussed extensively, and not for a long time, so others may have different understanding.

Types must agree in standard mode too, of course (at run-time).

# Michael O'Brien (17 years ago)

I've only used named rest arguments

function f(obj, ...items)

I forgot you could do:

function f(obj, ...)

you're right - no overhead.

Another RI bug - that form won't work when you invoke it:

ERROR MachError: defining out-of-bounds temporary (near a.as: 5:4-5.3)

Michael

# Mark S. Miller (17 years ago)

[+es3.x-discuss]

On Fri, May 9, 2008 at 10:43 AM, Lars Hansen <lhansen at adobe.com> wrote:

In strict code ("use strict") the number of passed arguments must match the number of expected arguments. This has been agreed upon.

Hi Lars, much as it pains me to raise this again, it has not been agreed upon. In order for ES3.1 strict mode to be a fail-stop subset of ES4 strict mode, I don't see how we could possibly agree on this. Please include es3.x-discuss on further discussion of this topic.

ES3.1 must define a language that depends only on features that will parse successfully on 3/4 of the current major browsers. Therefore, it cannot adopt ES4's notations for either optional or rest arguments. Instead, I have proposed that in ES3.1 strict mode, and therefore in ES4 strict mode as well:

  • If a function is invoked with fewer arguments than its declared parameters, the remaining parameters are bound to undefined. If an ES4 strict function wishes to reject calls with too few arguments, then it should declare undefined-rejecting types on these remaining parameters.

  • If a function is invoked with more arguments than its declared parameters, and if the function either mentions the magic name 'arguments' freely in its body or (ES4 only) declares rest parameters, then it is considered an unbounded arity function. Otherwise it is considered a bounded arity function.

  • If a strict bounded arity function is called with too many arguments, the call is rejected with a throw.

I would expect that if too few arguments are passed to a function with a typed interface then you get a type error unless the missing parameter has a type that includes "undefined" (ie no conversion takes place).

This should be the case for a strict function as well.

Signalling an error "because the function has a typed interface" is a variant, I guess, but it seems like an orthogonal concern.

Since ES3.1 has no typed interface, I will stay out of debates about the semantics of typed interfaces.

I would expect excess arguments to typed functions to be ignored silently, as they can be picked up by 'arguments' inside the function.

In loose mode, yes. It strict mode, only of 'arguments' is mentioned freely in the body of the function, or (ES4 only) if the function declares rest parameters.

# Mark S. Miller (17 years ago)

On Fri, May 9, 2008 at 11:21 AM, Lars Hansen <lhansen at adobe.com> wrote:

There are optional and rest arguments in ES4.

Regarding error reporting, strict mode is what gives you sane error checking (generally at run-time). Standard mode is for all you cowboys out there.

As a separate matter, that has been raised by others as well:

Since both modes are to be specified by upcoming standards documents, can we adopt some term other than "standard" for the mode we'd like to discourage? I propose "loose".

# Peter Hall (17 years ago)

Since both modes are to be specified by upcoming standards documents, can we adopt some term other than "standard" for the mode we'd like to discourage? I propose "loose".

I agree. But I think "lenient" sounds better.

Peter

# Michael O'Brien (17 years ago)

or relaxed

# Mark S. Miller (17 years ago)

On Mon, May 12, 2008 at 8:14 AM, Michael O'Brien <mob at mbedthis.com> wrote:

or relaxed

On May 12, 2008, at 8:10 AM, Peter Hall wrote:

I agree. But I think "lenient" sounds better.

I'm happy with either. I slightly prefer "relaxed". Both are better than "loose".