Bidding farewell to postfix decrement

I’m reviewing code as I prepare to remove postfix decrements in Swift 3.0. Here’s an example and a story.

Before my review, I had a postfix decrement on line 22, the one with the arc4random_uniform call:

Int(arc4random_uniform(UInt32(endBoundary--)))

This approach is conventional, or at least C-conventional because it is no longer going to be allowed in Swift. The decrement takes place after the random number generation, ensuring that the random number falls between 0 and endBoundary - 1. After the call,  endBoundary is decremented and the math that follows takes place with respect to that decremented endBoundary value.

At first, I toyed with scenarios for tweaking the endBoundary update. My gut told me to keep the boundary math close to the original location. I tried adding it to the same line with a semi-colon. Then I placed it on the next line. I considered using a defer statement and adjusting the math for the swap.

It wasn’t until I started properly adding comments that it became clear  in the algorithm story where the endBoundary adjustment belonged. Until commenting, I’d been acting reflexively:  I decremented the boundary count after rolling the dice because that is how I had always done it in C. But the boundary didn’t really affect my math until the swap. While I initially thought the update belonged before the nextIndex assignment, adding comments showed it fit better after.

This is a case of “but I did it this way in C, so it should work this way in Swift”. I was bemused when I first read the proposed language evolution change. Now that I’m trying to apply the change to my code, it’s making me see things in a new light.

6 Comments

  • Nice example! Mind warp fun this Swift 3.0 business.

  • Looks great. I also thought “do we really need so many explicit type conversions?” and I think the answer is “no” (see https://gist.github.com/ilyannn/ee39ce0c20155d40b48c )

    I also found randomShuffle() function in the Swift library, ironically it’s implemented via classic c-style for loop with decrement operator: https://github.com/apple/swift/blob/b9987e8b50fa6f313679b78e795e419dc442e235/stdlib/private/SwiftPrivate/SwiftPrivate.swift#L44

  • What about the use of postfix and prefix decrement and increment on indices? You can’t swap ++ for += 1 in that case.
    Doesn’t this:

        let hello = "hello"
        var i = hello.characters.indices
    
        i.startIndex++
        i.endIndex--
        let h = hello[i] // -> "ell"
    

    become this:

        let hello = "hello"
        var i = hello.characters.indices
    
        i.startIndex = i.startIndex.successor()
        i.endIndex = i.endIndex.predecessor()
        let h = hello[i] // -> "ell"
    

    I’m not crazy about the extra typing. Or is there a better way?

    • extension String {
          var butFirst: String {return String(characters.dropFirst())}
          var butLast: String {return String(characters.dropLast())}
      }
      
      "hello".butFirst.butLast
  • I guess I should have asked a more general question. How does one increment or decrement indices without typing out the whole successor/predecessor assignment?

    • Either type out the whole thing or use advancedBy. Indices are weird.