Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Allow passing extra unused parameters to a function #10811

Closed
DartBot opened this issue May 23, 2013 · 11 comments
Closed

Allow passing extra unused parameters to a function #10811

DartBot opened this issue May 23, 2013 · 11 comments
Labels
area-language Dart language related items (some items might be better tracked at github.com/dart-lang/language). P2 A bug or feature request we're likely to work on type-enhancement A request for a change that isn't a bug

Comments

@DartBot
Copy link

DartBot commented May 23, 2013

This issue was originally filed by Misko.Hever...@gmail.com


myFn(a) {};

myFn(); // fails not enough arguments
myFn(1); // Works
myFn(1,2) // fails too many arguments. I would like this to pass.

The above rule helps to catch bugs, but it makes it hard to write framework code.

class Framework {
  doSomething(fn) {
    // Framework calls developer function with all of the data which the developer could
    // possibly need. But the arguments are sorted by how likely it is that the developer
    // actually needs them. Most developers need just the first one.
    fn('veryCommon', 'somewhatCommon', 'rarelyUsed', 'almostNeverUsed');
  }
}

var f = new Framework();

// To call the above we need to do something like this.
// Notice we don't need most of the arguments, but we still have to declare them.
f.doSomething((a, b, c, d) => a > 1);

// We really want to write this:
f.doSomething((a) => a > 1);

// If we could do above then it would also be nice to write this:
noop(){}
f.doSomething(noop);

noop() and identity() are two most useful functions in functional programing, but they are useless in dart, since the argument length is unlikely to match the caller.

Here is an example of functional library: https://github.com/documentcloud/underscore/blob/master/underscore.js

Notice how often _.identiy is referenced. The above code could not be ported to dart as is.

But there is another issue. As a framework developer I discover that I need to add one more argument to the callback.
So I change my framework from
    fn('veryCommon', 'somewhatCommon', 'rarelyUsed', 'almostNeverUsed');
    fn('veryCommon', 'somewhatCommon', 'rarelyUsed', 'almostNeverUsed', 'newArgument');

Now I have not broken anyone since I am just passing one more parameter to function and no one is referencing it, yet all of the users of my framework now can't upgrade to the new version since their code would fail. They all have to add a bogus parameter to all of their function calls, which no one will reference. This is an issue.

REQUEST:
calling a function with fewer parameters then function requires should be an error. // This catches bugs
calling a function with more parameters then function requires should be OK. // This does not catch bugs, only restricts

@justinfagnani
Copy link
Contributor

Set owner to @gbracha.
Added Area-Language, C1 labels.
Changed the title to: "Calling a function with more parameters then function requires should not throw error".

@gbracha
Copy link
Contributor

gbracha commented May 23, 2013

I think we should find a way to address this, but it won't be by allowing wholesale calls with the wrong arity. The current Dart rules do catch errors and allow for efficient execution as well.

Ideas to address the problem without turning Dart into Javascript might involve variants of Function.apply() that tolerate excess arguments. Something like Smalltalk's valueWithEnoughArguments:. We'll see if dart2js can tolerate this sort of thing. Or maybe someone will have a better idea.


Added Accepted label.

@justinfagnani
Copy link
Contributor

Bob noted that you can define several supported function signature and use is checks to dispatch.

typedef void OneArg(a);
typedef void TwoArgs(a, b);
typedef void TwoAndANamedArgs(a, b, c: null);

void foo(f) {
  if (f is OneArg) { f('a'); }
  else if (f is TwoArgs) { f('a', 'b'); }
  else if (f is TwoAndANamedArgs) { f('a', 'b', c: 'c'); }
}

@rakudrama
Copy link
Member

I disagree that dropping extra arguments does not catch bugs.
When I was porting code from Python, I saw something like

  if x.startswith('foo', 1):

I ported this as

  if (x.startsWith('foo', 1)) ...

But Dart's String.startsWith is defined as follows:

abstract bool startsWith(String other)

Without detecting unwanted extra parameters I would not found the error until much much later.

If a callback takes a number of values, perhaps group of values is better passed as an object that implements an interface. The interface can be extended without breaking existing clients.

@DartBot
Copy link
Author

DartBot commented May 23, 2013

This comment was originally written by Misko.H...@gmail.com


Some more thoughts.

We could say that the extra arguments on object is an error but on stand alone function it is fine.

x.startsWith('foo', 1) is an error because startsWith is a method on String

fn(a);

fn(1, 2); is not an error because it is a closure/function/callback.

=================

Doing this:
typedef void OneArg(a);
typedef void TwoArgs(a, b);
typedef void TwoAndANamedArgs(a, b, c: null);

is not a solution but a hack. There are 100s of placets where framework needs to call back into dev code and many of them are performance intensive, it would be expensive both runtime, as well as developer code to expect that the framework would do this everywhere.

=================

Calling with hashes is also not a good options since it would require that the writer of the callback would have to do extra work like this:

list.forEach((element:null) => ...);

To me this syntax implies that I can get called with no arguments, which is not the case.

@DartBot
Copy link
Author

DartBot commented May 23, 2013

This comment was originally written by @seaneagan


@sra: you could catch that bug via a compile time static warning, which could either be part of the language spec, or just an option in an IDE like "warn on extra arguments".

@blois
Copy link
Contributor

blois commented May 23, 2013

FWIW, this would be very nice for futures- it's extremely common to see future callback functions naming parameters '_' when the param could just be omitted.

Example (creates a fresh indexed DB database):
return indexedDB.deleteDatabase(dbName).then(
  // should be able to omit this parameter completely.
  (_) {
    return indexedDB.open(dbName);
  });

@lrhn
Copy link
Member

lrhn commented Jul 18, 2013

If we keep seeing uses like
 .then((_) { ... })
where the user don't want to specify an argument, maybe we should have a
 .then0(() { ... })
method too to support that use-case, rather than changing the language.


Removed Type-Defect label.
Added Type-Enhancement label.

@DartBot
Copy link
Author

DartBot commented Nov 4, 2013

This comment was originally written by @seaneagan


@9: or have then check the arity, and call accordingly:

var result = callback is _Nullary ? callback() : callback(arg);

typedef _Nullary();

@DartBot
Copy link
Author

DartBot commented Jan 2, 2014

This comment was originally written by Misko.H...@gmail.com


@andrew,

What you are describing puts the burden on the author of the method (user of the API/library). What the bug is requesting is that the burden is with the caller (the API/library developer).

@DartBot DartBot added Type-Enhancement area-language Dart language related items (some items might be better tracked at github.com/dart-lang/language). labels Jan 2, 2014
@kevmoo kevmoo added P2 A bug or feature request we're likely to work on type-enhancement A request for a change that isn't a bug and removed accepted labels Feb 29, 2016
@munificent munificent changed the title Calling a function with more parameters then function requires should not throw error Calling a function with more parameters than function requires should not throw error Dec 16, 2016
@munificent munificent changed the title Calling a function with more parameters than function requires should not throw error Allow passing extra unused parameters to a function Dec 16, 2016
@munificent munificent removed the C1 label Jun 20, 2018
@leafpetersen
Copy link
Member

I don't think this is worth keeping open. There are workarounds for now, and I don't see this on the radar of any of our existing frameworks.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
area-language Dart language related items (some items might be better tracked at github.com/dart-lang/language). P2 A bug or feature request we're likely to work on type-enhancement A request for a change that isn't a bug
Projects
None yet
Development

No branches or pull requests

9 participants