These replies leave me increasingly convinced it would be positive to add this language feature.
Addressing the suggestions:
-
func loopN(_ count: Int, _ action: () -> ()) {
for _ in 0 ..< count {
action()
}
}
loopN(10) {
print("Hi!")
}
This highlights that Swift could provide a built-in function rather than a new keyword/language feature. I prefer a new keyword/language feature.
If this solution were not built-in to Swift, it would have the issue of scalability (has to be written many times, perhaps once per app, or once per engineering group), and potential for incorrectness (range logic is easy to get wrong), and confusion. (Why are we creating a variable we don't need? Isn't that a bad practice? Is there a better way?)
-
(1..<10).forEach { print($0) }
The fact that people in this thread wonder whether you meant to do this 9 times or 10 times is great evidence of the unnecessary risk of this solution. Ranges are easy to get wrong. Extensions don't scale well for reasons listed above. Extensions also aren't available in all environments (e.g. online Swift learning, interviews, leetcode, etc). An extension on an integer is perhaps a little unintuitive. I don't consider repetition a property or functionality of an integer.
Conversely, a keyword and a count is simple to get right, enjoyable to write, and universally available.
-
for _ in repeatElement((), count: n) {}
If you dropped the repeat, it's similar to solution 1. Building a new function into Swift is an alternative to adding a new keyword/language feature. I don't have a terribly strong preference on which way to go.
Solution 1, if added to Swift, would be better than solution 3 for the proposed use-case. Creating a list of void whose elements are discarded adds levels of indirection. The engineer must think:
a) I'll create a list of N elements
b) What type should that be? Can I provide any sensible type?
c) I guess void works.
d) What about warnings from unused variables?
e) I guess I'll use the underscore
f) Is there a better way? Best practice is to avoid unused/discarded variables in the first place.
g) No, there isn't. (Perhaps we should add this language feature to Swift some day.)
h) Ok, let's just go with this.
To go back to my ask:
Every time I do:
for _ in 0..<N {} I cringe and consider whether Swift does have a better way. Based on the replies so far it seems Swift does not have a better way.
I haven't read the historical posts yet. I'll read that once I have a good time to do so. If anyone has the context and wishes to summarize why this hasn't happened yet, please do.
Can anyone provide a currently existing way that's actually better, than this below?
for N {}
Are there any disadvantages to adding it? The only I see are:
- Effort to add to Swift (minimal, I imagine).
- Additional concept for the engineer to keep in their head.
Regarding 2, I don't consider this a major issue as it's a very simple concept to understand. Any engineer who wishes not to learn it can simply use other ways. Anyone who comes across it for the first time can easily guess what it does.
The advantages of for N are clear. Simplicity is priceless in software engineering. Simplicity avoids the risk of bugs and makes it easier to solve hard problems. I also argue it's more enjoyable to write for N than for _ in 0..<N. If Swift doesn't have a concise/clean way to take a count and a scope and execute the scope count times, I still think it should be added.