This is just syntactic sugar, but it would be useful if instead of:
for(int i = 0; i < 5; i++) {
print(i); // prints 0, 1, 2, 3, 4
}
We could just do:
for(5) {
print(i); // prints 0, 1, 2, 3, 4
}
I think it's not something that should be in the language. Specially, the for syntax is not appropriate for this. Maybe it should be in the standard library, as an extension for int, like the one Ruby has:
void main() {
5.times(print); // prints 0, 1, 2, 3, 4
}
extension IntegerExtension on int {
void times(void Function(int index) fn) {
for (int i = 0; i < this; i++) {
fn(i);
}
}
}
Although Dart does not support passing blocks like Ruby, it would still be nice. In this case, however, it should be proposed on https://github.com/dart-lang/sdk
I don't see a problem for using this on for, IMO for is like a generic loop statement, there's for (var i = 0; i < 2; i++) and for (var x in collection), the for word in English doesn't have any connotations that resemble a loop, while at least sounds that something will happen while something is true, while carries a connotation of time.
Honestly I don't mind if this is implemented as a function for int, I will leave this decision for the Dart team as they have much more experience and perception on this matter than I have.
I've never seen any language using for this way and I really find it weird.
The keyword for resembles me of the mathematical "for all" (∀). E.g. for (item in items) do(item); resembles me ∀ item ∈ items, do(item).
I would support, tho, a literal range syntax. Something like:
for (i in 0..4) {
print(i);
}
I'm with @mateusfccp. I don't think the feature adds enough value to be worth adding directly to the language. I think a times extension method on int is a great solution. In particular, the latter gives you a way to capture the index in a variable, which the proposed syntax lacks.
Perfect by me, as I said before, I don't mind at all, and I was sure you guys would add much value to the proposal, as the use of the integer itself.
For what it's worth, here's the implementation for a range function:
Iterable<int> range({int start = 0, int end = 0, int step = 1}) sync* {
assert(step > 0);
if (start > end) {
for (var value = start; value >= end; value -= step) {
yield value;
}
} else {
for (var value = start; value <= end; value += step) {
yield value;
}
}
}
Which allows:
for (final value in range(end: 5)) {
print(value); // 0 1 2 3 4 5
}
for (final value in range(start: 5, end: 10)) {
print(value); // 5 6 7 8 9 10
}
for (final value in range(end: 10, step: 2)) {
print(value); // 0 2 4 6 8 10
}
for (final value in range(start: 10, end: 5)) {
print(value); // 10 9 8 7 6 5
}
Out of curiosity, why did you make the (start > end) the if condition? Not that it makes a difference, but usually people prefer the most common case to be the if clause.
for(5) { print(i); // prints 0, 1, 2, 3, 4 }
Where would that i come from? This comes as a surprise.
Even Remi's solution is kind of hard to grasp: will end be inclusive or not? Depending on where you come from, you will interpret it differently, and I can see this feature being a major source of hard to tracking bugs.
A times extension method would fix all of those doubts, wouldn't it? The name says "times" so you should expect that many iterations, the docs just have to be clear that since this is an iteration, the numeric value being passed to the lambda will start at 0, so end is not inclusive, as that's what most people should expect from an iteration anyways.
I'm going to close this out, because I think we're pretty well settled that extension methods are sufficient for providing a nice user experience for these cases.
I think we are settled that a method is the best way, people gave here a way to impelent this right now with extension methods, just as a temporary solution, I think this is very welcome to be part of the SDK as a method for int, so this should remain open and be transfered to the SDK repo so the method could be implemented there.
people gave here a way to impelent this right now with extension methods, just as a temporary solution
I don't look at that as being a temporary solution. If we added it to the core library, it would likely be an extension method there. Putting it in the core library doesn't really give it any useful special powers beyond saving you an import. I could be wrong, but this seems like the kind of functionality that's well served by just being in a package.
If you'd like, though, please do file an issue on the SDK repo. I don't work directly on the core libs and those folks may find it compelling.
I understand your point, I just really don't like having all of those tiny packages that do one simple thing. I imagine if we adopt this for 100 tiny improvements we would have 100 packages, whereas if all of them were incorporated into the SDK than we would have a stronger SDK.
I will file this into the SDK repo, thanks for your time Bob.
Most helpful comment
I've never seen any language using
forthis way and I really find it weird.The keyword
forresembles me of the mathematical "for all" (∀). E.g.for (item in items) do(item);resembles me∀ item ∈ items, do(item).I would support, tho, a literal range syntax. Something like: