8

In many projects this control structure is ideal for readability:

forCount( 40 )
 {
 // this block is run 40 times
 }

You can do exactly that in objective-C.

Given that Swift has a very different approach to macros than objective-c,

is there a way to create such a forCount(40) control structure in Swift projects?


Some similar concepts in Swift:

for _ in 1...40
 { // this block is run 40 times }

Using an ingenious extension to Int ...

40.times
 { // this block is run 40 times }
Community
  • 1
  • 1
Fattie
  • 27,874
  • 70
  • 431
  • 719
  • See also http://www.drewag.me/posts/7-cool-features-in-swift#extend-structs-and-literals. – Martin R Sep 17 '15 at 14:23
  • Hi Martin, the "5.times" extension trick is terrific, and I do thank you, but I was really wondering if there was a way to make wordHere(n) work syntactically, as one can easily when there's a preprocessor. As it says in the question. Not so much looking for the shortest way to do it. – Fattie Sep 17 '15 at 14:25
  • Then I misunderstood your question (sorry for that!), I have re-opened it. – Martin R Sep 17 '15 at 14:52
  • au contraire, thanks all around! questions were meant to be closed an opened and closed! – Fattie Sep 17 '15 at 15:20
  • Adding a “repeat N times” feature to the Swift language is currently discussed on the Swift evolution forum: https://forums.swift.org/t/straightforward-code-repetition/13828. – Martin R Jun 28 '18 at 11:31
  • @MartinR, fascinating, thanks for that ! Key for every game engineer – Fattie Jun 28 '18 at 11:55
  • That forum is open to everyone – you are welcome to contribute your arguments! – Martin R Jun 28 '18 at 12:07
  • I'd be too shy man! it's all pro users there! :O – Fattie Jun 28 '18 at 16:53

2 Answers2

12

There are no preprocessor macros in Swift, but you can define a global function taking the iteration count and a closure as arguments:

func forCount(count : Int, @noescape block : () -> ()) {
    for _ in 0 ..< count {
        block()
    }
}

With the "trailing closure syntax", it looks like a built-in control statement:

forCount(40) {
    print("*")
}

The @noescape attribute allows the compile to make some optimizations and to refer to instance variables without using self, see @noescape attribute in Swift 1.2 for more information.

As of Swift 3, "noescape" is the default attribute for function parameters:

func forCount(_ count: Int, block: () -> ()) {
    for _ in 0 ..< count {
        block()
    }
}
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
2

you can do

let resultArr = (0..<n).map{$0+5}

or

(0..<n).forEach{print("Here\($0)")}
GreatWiz
  • 735
  • 4
  • 8
  • 1
    By far the cleanest, easiest-to-read, most-Swifty syntax -- leverage ```map``` to avoid extensions and / or non-Swifty global functions. – Small Talk Jun 28 '23 at 11:14