Creating function with variable number of argument

2019-01-07 23:46发布

问题:

I am looking for a way to create a function with a variable number of arguments or parameters in Dart. I know I could create an array parameter instead, but I would prefer to not do that because I'm working on a library where syntactic brevity is important.

For example, in plain JavaScript, we could do something like this (borrowed from here):

function superHeroes() {
  for (var i = 0; i < arguments.length; i++) {
    console.log("There's no stopping " + arguments[i]);
  }
}

superHeroes('UberMan', 'Exceptional Woman', 'The Hunk');

However, in dart, that code will not run. Is there a way to do the same thing in dart? If not, is this something that is on the roadmap?

回答1:

You can't do that for now.

I don't really know if varargs will come back - they were there some times ago but have been removed.

However it is possible to emulate varargs with Emulating functions. See the below code snippet.

typedef dynamic OnCall(List);

class VarargsFunction extends Function {
  OnCall _onCall;

  VarargsFunction(this._onCall);

  call() => _onCall([]);

  noSuchMethod(Invocation invocation) {
    final arguments = invocation.positionalArguments;
    return _onCall(arguments);
  }
}

main() {
  final superHeroes = new VarargsFunction((arguments) {
    for (final superHero in arguments) {
      print("There's no stopping ${superHero}");
    }
  });
  superHeroes('UberMan', 'Exceptional Woman', 'The Hunk');
}


回答2:

I played around a little with Alexandre Ardhuin's answer and found that we can tweak a couple of things to make this work in the current version of Dart:

class VarArgsClass {
  noSuchMethod(InvocationMirror invocation) {
    if (invocation.memberName == 'superheroes') {
      this.superheroes(invocation.positionalArguments);
    }
  }

  void superheroes(List<String> heroNames) {
    for (final superHero in heroNames) {
      print("There's no stopping ${superHero}!");
    }
  }
}

main() {
  new VarArgsClass().superheroes('UberMan', 'Exceptional Woman', 'The Hunk');
}

This has lots of problems, including:

  • A warning is generated wherever you call superheroes() because the signature doesn't match your parameters.
  • More manual checking would need to be done to make sure the list of arguments passed to superheroes is really a List<String>.
  • Needing to check the member name in noSuchMethod() makes it more likely you'll forget to change the 'superheroes' string if you change the method name.
  • Reflection makes the code path harder to trace.

BUT if you are fine with all of those issues, then this gets the job done.



回答3:

If you are really into syntactic brevity, just declare a function/method with say 10 optional positional parameters and be done. It's unlikely someone will call that with more than 10 arguments.

If it sounds like a hack, that's because it is a hack. But I've seen the Dart team doing the same :-)



回答4:

For the example you've written, I think you're best off using a list. Sorry about that!

I'm looking at dartbug.com, but I don't see a feature request for this. You're definitely welcome to create one!



标签: dart