Coder Social home page Coder Social logo

Comments (49)

vcraescu avatar vcraescu commented on August 25, 2024 31

6 years and still no var args? 😀

from language.

devxpy avatar devxpy commented on August 25, 2024 29

Its almost essential, since dart doesn't inherit constructors.

Extending a class requires one to look up the full constructor of parent.

For me, that's just too much typing.

Like, this

class CustomPageRoute<T> extends MaterialPageRoute<T> {
  CustomPageRoute(*args, **kwargs) : super(*args, **kwargs);
}

compared to this

class CustomPageRoute<T> extends MaterialPageRoute<T> {
  CustomPageRoute({
    @required builder,
    RouteSettings settings,
    maintainState: true,
    bool fullscreenDialog: false,
  }): super(
          builder: builder,
          settings: settings,
          maintainState: maintainState,
          fullscreenDialog: fullscreenDialog,
        );
}

I get the reasons behind not inheriting constructors. Explicit is better than implicit. But *args, **kwargs is a great way to prevent excessive typing.

from language.

LukaGiorgadze avatar LukaGiorgadze commented on August 25, 2024 14

Waiting for this.

from language.

SzczurekYT avatar SzczurekYT commented on August 25, 2024 13

We really need this. and dart is falling behind many other laguages. Java, Javascript, Python, C# all these langages have varargs and dart doesn't. I know that dart is pretty new, laguage but It would be really cool if we had this.

I hope that someona will finally implement this.

from language.

hereisderek avatar hereisderek commented on August 25, 2024 10

issue opened on 23 Jan 2014

from language.

sarankumar-ns avatar sarankumar-ns commented on August 25, 2024 9

9 years and counting...

In my case, I need to pass varargs in JS Interop function. It expects varargs instead of List.

from language.

bernaferrari avatar bernaferrari commented on August 25, 2024 5

I'm not sure this will ever be implemented, but with Records someone could make a typeDef vararg = record and inline (()) into ()

image

from language.

DartBot avatar DartBot commented on August 25, 2024 4

This comment was originally written by [email protected]


Yah, I agree that supporting varargs just for the sake of porting python code is not a good argument.

However, I would say that supporting varargs for the sake of having a clean, flexible, readable langauge is a good argument.

We can get around the lack of vararg support using tricks like the one described in Yu Asakusa's blog post. (Nice, by the way!). But to me built-in vararg support would still be nice to have.

At this point I suppose the decision on this rests in the hands of the Dart committee (or however these things get decided? Is there a benevolent dart-tator for life?)

from language.

Sunbreak avatar Sunbreak commented on August 25, 2024 4

9 years and counting...

In my case, I need to pass varargs in JS Interop function. It expects varargs instead of List.

BTW, you could try fixed arguments instead of List: dart-lang/sdk#38578 (comment)

Or @staticInterop: flutter/flutter#97357 (comment) and https://github.com/dart-lang/site-www/pull/4528/files

Or comment on dart-lang/sdk#35084

from language.

jacob314 avatar jacob314 commented on August 25, 2024 3

Supporting variable numbers of arguments would improve console logging methods in dart:html and for Flutter.

from language.

CEbbinghaus avatar CEbbinghaus commented on August 25, 2024 3

Variadic arguments are going to be very helpful, and make Prototyping as well as Writing code Easier.

If both C# and JS have them then that means that Dart which sits in between is starting to fall behind

from language.

Levi-Lesches avatar Levi-Lesches commented on August 25, 2024 3

For those saying they need this feature, can you elaborate on why using a List won't work? In cases where all the arguments are of the same type, you can use List<int> or another type, and when they're not, you'd use List<Object> or just List. Either way, you lose type safety, so one isn't worse than the other.

from language.

DartBot avatar DartBot commented on August 25, 2024 2

This comment was originally written by @seaneagan


Strawman:

varPositionals(required, [optional, String ...rest]) {
  assert(rest is List<String>);
}
varNamed (required, {optional, String ...rest}) {
  assert(rest is Map<Symbol, String>);
}

(...rest is used by ES6)

from language.

simc avatar simc commented on August 25, 2024 2

Any news on this? I'm working on a "ramda like" library and the lack of varargs is really limiting :/

from language.

esenmx avatar esenmx commented on August 25, 2024 2

For those saying they need this feature, can you elaborate on why using a List won't work? In cases where all the arguments are of the same type, you can use List<int> or another type, and when they're not, you'd use List<Object> or just List. Either way, you lose type safety, so one isn't worse than the other.

It's mostly about code quality.
Very very simple example:

final a = 42;
final b = 90;

void argsFn(...int args) {};
void arrayFn(List<int> array) {};

main() {
  argsFn(a, b);
  arrayFn(<int>[a, b]);
};

I would choose argsFn all time...

Also don't forget SQL has variadic parameters and using array won't work for the SQL code generators where args needed because arrays and args are fundamentally different things. So it's literally necessity after all.

Edit: Workarounds are always possible but I'm and most of you as I guess not big fan of language of workarounds...

from language.

mmcdon20 avatar mmcdon20 commented on August 25, 2024 2

If dart ever does implement varargs, it would be nice if it supported using the equivalent of collection if and collection for at the call site, otherwise it would seem less expressive than just accepting a collection literal.

void argsFn(...int args) {}

void main() {
  argsFn(
    for (int i = 0; i < 10; i++)
      if (i % 2 == 0) i,
  );
}

Additionally, I think it would be nice if you weren't limited to only collecting the arguments into a List<A>. Why not allow varargs to collect to a Set<A> or Map<A, B> or Iterable<A> or even custom user defined data structures?

void varArgsList(...List<int> args) {}
void varArgsSet(...Set<int> args) {}
void varArgsMap(...Map<int, int> args) {}
void varArgsIterable(...Iterable<int> args) {}
void varArgsCustom(...Custom<int> args) {}

A rough idea for how this might work, is that perhaps classes with an .of constructor can be used with varargs. If the constructor accepts an Iterable<A> like with List<A>.of and Set<A>.of then the arguments are collected into an Iterable<A> and passed to the .of constructor. If the .of constructor accepts a Map<A. B> instead, like with Map<A, B>.of, then at the callsite you would pass in the varargs as key/value pairs.

Iterable itself, does not have an .of constructor, but perhaps a special case could be made for the Iterable type, which would ideally collect the arguments as a lazy iterable (like a sync* function).

Basically this:

void varArgsList(...List<int> args) {}
void varArgsSet(...Set<int> args) {}
void varArgsMap(...Map<int, int> args) {}
void varArgsIterable(...Iterable<int> args) {}
void varArgsCustom(...Custom<int> args) {}

void main() {
  varArgsList(for (int i = 0; i < 10; i++) if (i % 2 == 0) i);
  varArgsSet(for (int i = 0; i < 10; i++) if (i % 2 == 0) i);
  varArgsMap(for (int i = 0; i < 10; i++) if (i % 2 == 0) i: i);
  varArgsIterable(for (int i = 0; i < 10; i++) if (i % 2 == 0) i);
  varArgsCustom(for (int i = 0; i < 10; i++) if (i % 2 == 0) i);
}

Could be syntactic sugar for this:

void varArgsList(List<int> args) {}
void varArgsSet(Set<int> args) {}
void varArgsMap(Map<int, int> args) {}
void varArgsIterable(Iterable<int> args) {}
void varArgsCustom(Custom<int> args) {}

void main() {
  varArgsList(List<int>.of(() sync* {
    for (int i = 0; i < 10; i++) if (i % 2 == 0) yield i;
  }()));
  varArgsSet(Set<int>.of(() sync* {
    for (int i = 0; i < 10; i++) if (i % 2 == 0) yield i;
  }()));
  varArgsMap(Map<int, int>.of({
    for (int i = 0; i < 10; i++)
      if (i % 2 == 0) i: i,
  }));
  varArgsIterable(() sync* {
    for (int i = 0; i < 10; i++) if (i % 2 == 0) yield i;
  }());
  varArgsCustom(Custom<int>.of(() sync* {
    for (int i = 0; i < 10; i++) if (i % 2 == 0) yield i;
  }()));
}

from language.

munificent avatar munificent commented on August 25, 2024 2

As for suggestion 1, it's pretty much a given that if dart adds varargs, it will support spreads ... at the call site. So why not for and if as well?

Yeah, if we do varargs, I certainly want to push to support all three of those.

from language.

Policy56 avatar Policy56 commented on August 25, 2024 2

On this 1st April, 8 years after the issue open, nothing ...
Maybe a fool joke on this day ?

from language.

jodinathan avatar jodinathan commented on August 25, 2024 2

this could be also used with js_bindings to have nice interoped variadic methods with JS

from language.

fcole90 avatar fcole90 commented on August 25, 2024 1

Hi, I just discovered a use case where I think using arguments unpacking to be the most elegant solution. However, I'm new to Dart so I might be wrong.

I have a function in Dart which has some optional arguments

List<num> arange(num start, [num end, num step = 1]) {
  if (end == null) {
    end = start;
    start = 0;
  }
  int length = (end - start) ~/ step;
  return List<num>.generate(length, (i) => start + i * step);
}

I want to call this function from Javascript, so I wrote my main as this:

import 'dart:js';

void main() {
  context['arange'] = arange;
}

However, when called from Javascript, this returns a Dart object, while what I want was a Javascript array. So the solution would be to use JsObject.jsify to convert the Dart list into a Javascript array.

If argument unpacking was available the implementation would be a simple one-liner edit using anonymous functions:

context['arange'] = (varargs) => JsObject.jsify(arange(*varargs));

Instead, without it, I think that I would need to write another function with the same signature as the function I want to convert, for each function I want to expose in this way.

JsObject arangeJS(num start, [num end, num step = 1]) {
  return JsObject.jsify(arange(start, end, step));
}

void main() {
  context['arange'] = arangeJS;
}

I might be missing something, as I'm new to the language, but this is the best I could come out with. Please feel free to comment or point any mistake.

Full main.dart:

import 'dart:js';

void main() {
  context['arange'] = arangeJS;
}

List<num> arange(num start, [num end, num step = 1]) {
  if (end == null) {
    end = start;
    start = 0;
  }
  int length = (end - start) ~/ step;
  return List<num>.generate(length, (i) => start + i * step);
}

JsObject arangeJS(num start, [num end, num step = 1]) {
  return JsObject.jsify(arange(start, end, step));
}

Compiled with dart2js -O2 -o arange.js main.dart --packages=.packages.

from language.

mateusfccp avatar mateusfccp commented on August 25, 2024 1

I am also looking forward to this. Made some memoization methods and had to write one method for each arg count, up to 4. Really cumbersome and breaks DRY principles...

from language.

omahili avatar omahili commented on August 25, 2024 1

This would be really useful for utility functions which need to be versatile.

For example:

Function debounce(Function func, int milliseconds) {
  Timer timer;
  return (arg) {
    if (timer != null) {
      timer.cancel();
    }

    timer = Timer(Duration(milliseconds: milliseconds), () => func(arg));
  };
}

Which unfortunately can be used only with fixed arguments.

As @seaneagan pointed out, something similar to rest parameters in JavaScript would be very useful:

Function debounce(Function func, int milliseconds) {
  Timer timer;
  return (...arg) {
    if (timer != null) {
      timer.cancel();
    }

    timer = Timer(Duration(milliseconds: milliseconds), () => func(...arg));
  };
}

from language.

cedvdb avatar cedvdb commented on August 25, 2024 1

To add an example of usefulness of this : There was a request on to add the index to list.forEach in the dart language. Unfortunately it couldn't be done because dart doesn't allow to pass more arguments than the function can take in.

Imo this is kinda related to varargs where you should be able to pass more arguments than you need to, to a function.

from language.

ykmnkmi avatar ykmnkmi commented on August 25, 2024 1

@mmcdon20 too complicated and why not T ...name:

int sum(int ...args);
int sumFn(Iterable<int> args);

also there are other issues for maps and objects.

from language.

sgjesse avatar sgjesse commented on August 25, 2024

Removed Type-Defect label.
Added Type-Enhancement, Area-Language, Triaged labels.

from language.

DartBot avatar DartBot commented on August 25, 2024

This comment was originally written by [email protected]


+1 for the Strawman in #­2. I like the '...' syntax, because it (1) semantically jibes for me, and (2) it echoes coffeescript varargs syntax, which folks are already familiar with.

from language.

DartBot avatar DartBot commented on August 25, 2024

This comment was originally written by @zoechi


As it's just another sytax for a parameter of type List, why not just stay with List?

from language.

DartBot avatar DartBot commented on August 25, 2024

This comment was originally written by [email protected]


I'm not sure that using a 'List' parameter has the effect I'm looking for.

If I used a 'List' parameter, wouldn't I have to explicitly put the arguments into a list when I call the function?

For example, if I have:

varPositionals (required, [optional, List theRest])

wouldn't I need to call this like:

varPositionals('required', 'optional', ['a', 'b', 'c'])

?

I'm looking instead for something more like python's behavior e.g. I want to call the function like this:

varPositionals('required', 'optional', 'a', 'b', 'c')

and have 'a', 'b', and 'c' get aggregated into the variable 'theRest'.

I hope that this helps to clarify.

from language.

DartBot avatar DartBot commented on August 25, 2024

This comment was originally written by @zoechi


I understand your request but I'm not sure if special syntax is worth this little (IMHO) gain.

from language.

DartBot avatar DartBot commented on August 25, 2024

This comment was originally written by [email protected]


This would make porting python code to dart much cleaner.

As a user of Dart, I personally do not find it important to make it easy to port code from Python to Dart, or from any language for that matter (perhaps except for JavaScript). After all, Dart and Python are different languages.

I am not saying that supporting variadic functions in Dart is useless. But “Python supports them, so Dart should also support them to make porting easy” is a weak argument.

By the way, it is possible to emulate variadic functions in Dart by a dirty hack in case you need them for some reason. See my post at http://yuasakusa.github.io/dart/2014/01/23/dart-variadic.html.

from language.

gbracha avatar gbracha commented on August 25, 2024

Set owner to @gbracha.
Added Accepted label.

from language.

gil0mendes avatar gil0mendes commented on August 25, 2024

I see that task has been assigned to someone... but it's been a year since the last activity... my question is... how much longer we have to wait for this syntax?

from language.

seaneagan avatar seaneagan commented on August 25, 2024

Someone will need to create a dart enhancement proposal for it first.

from language.

roman-vanesyan avatar roman-vanesyan commented on August 25, 2024

Is it possible that this feature will be included into the Dart 2.0?

from language.

matanlurey avatar matanlurey commented on August 25, 2024

No, it is not planned (or started)

from language.

zoechi avatar zoechi commented on August 25, 2024

@devxpy There were discussions about improving constructors, but as distinct topic, but most improvements are planned after Dart 2. Dart 2 was mostly about moving to common frontend (CFE) and sound type system.

from language.

vp2177 avatar vp2177 commented on August 25, 2024

Question to the original reporters of this issue:
Given that a variable number of arguments of the same type – ex. List<String> *args Python style or List<String> ...args JS style – wouldn't be too useful, how do you imagine expressing their types? List<Object> ...args on the other hand forces the function to forego static typing.

What is the prior art on statically typed varargs?

from language.

natebosch avatar natebosch commented on August 25, 2024

I'm not sure if varags would solve the forwarding case or not. For another discussion around wrapping functions of unknown arity and argument type see #157

from language.

ali-1989 avatar ali-1989 commented on August 25, 2024

Please add this to Dart.
see: https://stackoverflow.com/questions/3941517/converting-list-to-args-when-calling-function

from language.

liudonghua123 avatar liudonghua123 commented on August 25, 2024

I have some code like the following.

import 'dart:async';

typedef throttle_debounce_callback = dynamic Function(List<dynamic>? positionalArguments,
    [Map<Symbol, dynamic>? namedArguments]);

throttle_debounce_callback throttle(Function callback, int interval) {
  var enableCall = true;
  return (List<dynamic>? positionalArguments, [Map<Symbol, dynamic>? namedArguments]) {
    if (!enableCall) return;
    enableCall = false;
    Function.apply(callback, positionalArguments, namedArguments);
    Future.delayed(Duration(milliseconds: interval), () => enableCall = true);
  };
}

throttle_debounce_callback debounce(Function callback, int interval) {
  Timer? debounceTimeoutId;
  return (List<dynamic>? positionalArguments, [Map<Symbol, dynamic>? namedArguments]) {
    debounceTimeoutId?.cancel();
    debounceTimeoutId =
        Timer(Duration(milliseconds: interval), () => Function.apply(callback, positionalArguments, namedArguments));
  };
}

However the shortcoming is that I need to pass positional arguments as a list, instead of variable length arguments. I hope I can write code like this.

import 'dart:async';

typedef throttle_debounce_callback = dynamic Function([dynamic ...positionalArguments],
    [Map<Symbol, dynamic>? namedArguments]);

throttle_debounce_callback throttle(Function callback, int interval) {
  var enableCall = true;
  return ([dynamic ...positionalArguments], [Map<Symbol, dynamic>? namedArguments]) {
    if (!enableCall) return;
    enableCall = false;
    Function.apply(callback, positionalArguments, namedArguments);
    Future.delayed(Duration(milliseconds: interval), () => enableCall = true);
  };
}

throttle_debounce_callback debounce(Function callback, int interval) {
  Timer? debounceTimeoutId;
  return ([dynamic ...positionalArguments], [Map<Symbol, dynamic>? namedArguments]) {
    debounceTimeoutId?.cancel();
    debounceTimeoutId =
        Timer(Duration(milliseconds: interval), () => Function.apply(callback, positionalArguments, namedArguments));
  };
}

This would be more user-friendly.

Now the test code need to be

import 'dart:async';

import 'package:simple_throttle_debounce/simple_throttle_debounce.dart';

void main() async {
  var limit = 100;
  var tick = 0;
  var interval = 1000;
  var simpleTask = (tick) => print('tick: $tick');
  var throttleSimpleTask = throttle(simpleTask, interval);
  var debounceSimpleTask = debounce(simpleTask, interval);
  while (true) {
    print(tick);
    throttleSimpleTask([tick]);
    // debounceSimpleTask([tick]);
    await Future.delayed(Duration(milliseconds: 100), () => tick++);
    if (tick > limit) break;
  }
}

from language.

sodiboo avatar sodiboo commented on August 25, 2024

Good point cedvdb, then non-vararg functions could also have static type safety with spread arguments as long as all the rest of the parameters are optional and the same type as the list

Also, the hash functions of quiver could benefit from varags, then it could be reduced to a single hash function instead of hash2, hash3, hash4, and hashObjects if you have more - I'd like to suggest that a list of the same type as the varags could also be passed to the function and act like a positional argument, that way you don't need to explicitly spread it just to become a list within the function again (possible performance improvement? wouldn't create a new list, whereas spread args i'd imagine creates a new list?)

from language.

sae13 avatar sae13 commented on August 25, 2024

wait

from language.

esenmx avatar esenmx commented on August 25, 2024

I think multiple assignment is also related to this feature. Both args and multiple assignment can reduce significantly amount of code written in many cases.

from language.

ykmnkmi avatar ykmnkmi commented on August 25, 2024

Is a dart way to use different method for collections/arguments, like add/addAll, build/buildAll, ....
Easy way to implement this is transforming argsFn(varargs int args) to argsFn(List<int> args) and replace calls with list in CFE.

from language.

Levi-Lesches avatar Levi-Lesches commented on August 25, 2024
final a = 42;
final b = 90;

void argsFn(...int args) {};
void arrayFn(List<int> array) {};

main() {
  argsFn(a, b);
  arrayFn(<int>[a, b]);
};

Except if a and b are known to be ints, which they have to be in order to be passed to argsFn, then you don't need to include <int> around the brackets, so the code ends up being just as short:

final a = 42;
final b = 90;

void fn1(...int args) {}
void fn2(List<int> array) {}

void main() {
  fn2(a, b);
  fn2([a, b]);
}

As for code generators, well those can be considered workarounds in and of themselves, although I don't use them as much so I can't really sympathize. To clarify, I do think this would be a neat feature (if all the var-args were of the same type and collapsed to a List<E>), I was just trying to gauge how high of a priority this should be when there are other high-profile issues going around.

from language.

mmcdon20 avatar mmcdon20 commented on August 25, 2024

too complicated

@ykmnkmi which part is too complicated?

To summarize, I suggested 2 things:

  1. varargs should allow if and for at the call site.
  2. You should be able to pick a data structure to collect the arguments into.

If you think about it, dart already has varargs, its just limited to collection literals. And collection literals support the above features.

As for suggestion 1, it's pretty much a given that if dart adds varargs, it will support spreads ... at the call site. So why not for and if as well?

As for suggestion 2, I admit I expected this suggestion would be a bit more controversial. I can't think of any other programming language that allows you to do this, so it would be going against the norm. But it would add some more flexibility compared to only collecting the arguments as a List<T> like other programming languages do.

and why not T ...name

I don't have a preference between T ...name and ...T name.

from language.

Sunbreak avatar Sunbreak commented on August 25, 2024

Any progress on this? It is blocking dart-lang/sdk#38578

from language.

munificent avatar munificent commented on August 25, 2024

No progress yet. We're mostly focused on static metaprogramming, views, and pattern matching.

from language.

Sunbreak avatar Sunbreak commented on August 25, 2024

9 years and counting...

In my case, I need to pass varargs in JS Interop function. It expects varargs instead of List.

dart:ffi: Support variadic C functions is closed

I suppose dart:ffi or dart2wasm have more priority

from language.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.