In Swift, we often need to make our code repeat. Swift has made this easy to do while iterating through a range with a for
loop. But you don't always need to iterate through a range when repeating code, take the following example.
struct Card {
var rank: Rank
var suit: Suit
enum Rank {
case ace
case king
case queen
case jack
case number(Int)
}
enum Suit: Int {
case hearts = 1, diamonds, clubs, spades
}
static let newDeck: [Card] = { () -> [Card] in
var deck = [Card]()
for suits in 1...4 {
for ranks in 1...13 {
var currentRank : Card.Rank {
switch ranks {
case 1: return .ace
case let n where 2...10 ~= n: return .number(n)
case 11: return .jack
case 12: return .queen
case 13: return .king
default: return .number(-1) //will never happen
}
}
deck.append(Card(rank: currentRank, suit: Card.Suit(rawValue: suits)!))
}
}
return deck
}()
}
Now lets get a fresh deck of cards right out of the box:
var freshDeckOfCards = Card.newDeck
But I want to play a good game of poker, so we need to shuffle our cards. Here is our card shuffling extension:
extension Array where Element == Card {
mutating func shuffle() {
var shuffledArray = [Card]()
shuffledArray.reserveCapacity(count)
var totalCount : Int = count
var tempArray : [Card] = self
for _ in 0..<count {
shuffledArray.append(tempArray.remove(at: Int(arc4random_uniform(UInt32(totalCount)))))
totalCount -= 1
}
self = shuffledArray
}
}
Lastly, this is the top of the notch casino, so we need to shuffle our deck at least 11 times:
for _ in 1...11 {
freshDeckOfCards.shuffle()
}
//Our deck has been thoroughly shuffled
or lets take an exponentiation function for example
func myPow(_ base: Int, _ exponent: Int) -> Int {
var n = 1
for _ in 1...exponent {
n *= base
}
return n
}
var fifteenExponentTwo = myPow(15, 2) //225
In the last step of both of the provided examples lies the ambiguous part of our code that I would like to fix. The need to use an underscore and a range may be confusing to some new developers as all they need is to repeat a piece of code a specified number of times rather than iterate through a range. Also it is redundant code that makes overall readability suffer.
My Solution - repeat for
My solution involves the creation of a new, simple type of loop, a repeat for
loop.
In this loop you don't iterate through anything (range, array, etc.), the code within the loop is repeated for the specified number of times. To show you what I mean, let's fix our exponent function, myPow
.
func myPow(_ base: Int, _ exponent: Int) -> Int {
var n = 1
repeat for exponent { //repeat for loop in place of the for loop
n *= base
}
return n
}
var fifteenExponentTwo = myPow(15, 2) //225
Note: this will display an error if a user inputs a number less than 1.
One of the main and clearest benefits of this code is its straightforwardness and ergo, improve overall readability and reduce seemingly unnecessary code.
Naming Conventions
Some of the most popular naming suggestions that have been suggested include:
-
do
n
times
{...}
-
repeat for
n
{...}
-
repeat
n
{...}
-
do
n
{...}
-
repeat
{...}
for
n
And more naming conventions and suggestions are welcomed.