-
Notifications
You must be signed in to change notification settings - Fork 213
Feature Request: Variable Number of Arguments #1014
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Removed Type-Defect label. |
This comment was originally written by @seaneagan Strawman: varPositionals(required, [optional, String ...rest]) { (...rest is used by ES6) |
This comment was originally written by adors...@gmail.com +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. |
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? |
This comment was originally written by ado...@gmail.com 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. |
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. |
This comment was originally written by yu.asa...@gmail.com
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. |
This comment was originally written by ado...@gmail.com 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?) |
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? |
Someone will need to create a dart enhancement proposal for it first. |
Supporting variable numbers of arguments would improve console logging methods in dart:html and for Flutter. |
Is it possible that this feature will be included into the Dart 2.0? |
No, it is not planned (or started) |
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. |
@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. |
issue opened on 23 Jan 2014 |
Question to the original reporters of this issue: What is the prior art on statically typed varargs? |
Any news on this? I'm working on a "ramda like" library and the lack of varargs is really limiting :/ |
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 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 |
6 years and still no var args? 😀 |
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... |
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 |
Waiting for this. |
This would be really useful for utility functions which need to be versatile. For example:
Which unfortunately can be used only with fixed arguments. As @seaneagan pointed out, something similar to rest parameters in JavaScript would be very useful:
|
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 |
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;
}
} |
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. |
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 |
This comment has been minimized.
This comment has been minimized.
I think multiple assignment is also related to this feature. Both |
For those saying they need this feature, can you elaborate on why using a |
It's mostly about code quality. 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 Also don't forget SQL has variadic parameters and Edit: Workarounds are always possible but I'm and most of you as I guess not big fan of language of workarounds... |
Is a dart way to use different method for collections/arguments, like add/addAll, build/buildAll, .... |
Except if 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 |
If dart ever does implement varargs, it would be nice if it supported using the equivalent of 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 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
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;
}()));
} |
@mmcdon20 too complicated and why not int sum(int ...args);
int sumFn(Iterable<int> args); also there are other issues for maps and objects. |
@ykmnkmi which part is too complicated? To summarize, I suggested 2 things:
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 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
I don't have a preference between |
Yeah, if we do varargs, I certainly want to push to support all three of those. |
This comment was marked as off-topic.
This comment was marked as off-topic.
Any progress on this? It is blocking dart-lang/sdk#38578 |
No progress yet. We're mostly focused on static metaprogramming, views, and pattern matching. |
this could be also used with js_bindings to have nice interoped variadic methods with JS |
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. |
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 |
BTW, you could try fixed arguments instead of Or Or comment on dart-lang/sdk#35084 |
https://pub.dev/packages/dynamic_function if you use dynamic_function package for dart 3.7.2, you can allow optional positional and optional named arguments in the same function. See this gist: https://gist.github.com/javacommons/2446ce18252aa7623607f0ccd2aaf570 |
This issue was originally filed by ador...@gmail.com
It would be nice to have variable numbers of arguments, a la python splats.
This would make porting python code to dart much cleaner.
For example, I would like to do something like this:
The text was updated successfully, but these errors were encountered: