0

I'm new to Swift and is trying to learn the concept of extension. I saw this code in "the swift programming language", which tries to return the decimal digit 'n' places in from the right of the number. The code work fine, but I am struggling to understand how the code actually works.

Could someone explain it to me?

extension Int {
    subscript(var digitIndex: Int) -> Int {
        var decimalBase = 1
        while digitIndex > 0 {
            decimalBase *= 10
            --digitIndex
        }
        return (self / decimalBase) % 10
    }
}

746381295[0]
// returns 5
746381295[1]
// returns 9
746381295[2]
// returns 2
746381295[8]
// returns 7
746381295[9]
halfer
  • 19,824
  • 17
  • 99
  • 186
Thor
  • 9,638
  • 15
  • 62
  • 137

2 Answers2

2

Extensions work by adding capability to existing types, with the caveat that they cannot introduce their own storage. In the case in point:

/*1*/ extension Int {
/*2*/     subscript(var digitIndex: Int) -> Int {
/*3*/         var decimalBase = 1
/*4*/         while digitIndex > 0 {
/*5*/             decimalBase *= 10
/*6*/             --digitIndex
/*7*/         }
/*8*/         return (self / decimalBase) % 10
          }
      }

Line 1 defines the extension as applying to all Int types.

Line 2 is setting up a new subscript operator for an Int, which will allow you to have 12345[4] and produce 'something'. Lines 3-8 define that something.

The while in lines 4-8 is multiplying decimalBase by 10 for 'digitIndex' times. A bit of a weird way of doing it, but never mind. The upshot is if digitIndex is 1, decimalBase is 10; if it's 2, decimal base is 100; 3 it's 1000; etc.

The guts is in line 8. First it retrieves self. Since the extension applies to an Int, self will be that integer value. It then divides it by decimalBase, and because they're both integers, any fractional part will be lost. Therefore in the case of 746381295[2] decimalBase will be 100 so you get 7463812. Then it uses '%' to get the remainder of the division by 10. So 7463812 divided by 10 is 746381 with a remainder of 2. So the returned value is 2.

Hope that explains it.

Pre-empting your question, I might use for in this case, instead of the while:

for _ in 0..<digitIndex {
    decimalBase *= 10
}

I haven't thought too much about how often the above loops, it might run once to often or once too few, but you get the idea.

Even better would be to use the 'raising to the power' operator (not really sure what it's called).

decimalBase = 10 ^^ digitIndex

Then the whole definition could boil down to:

return (self / (10 ^^ digitIndex)) % 10

I will leave it to you to decide whether that's better or not.

Either way, I wouldn't really create this extension, and I assume it was just done for the purpose of demonstration.

Michael
  • 8,891
  • 3
  • 29
  • 42
  • Oh wow! that is an awesome answer! Thank you so much! Would up vote it a thousand times if I could! – Thor Feb 16 '16 at 04:43
1

Simply put, decimalBase is calculated to be 1 with an index of 0, 10 with an index of 1, 100 with an index of 2, 1,000 with an index of 3, and so on. In other words, decimalBase ends up equal to 10 ^ digitIndex.

So look at the case where digitIndex is 3, for instance. decimalBase will end up being 1,000, so:

746381259 / 1000 == 746381

and then:

746381 % 10 == 1

so that's how you get from 746381259[3] to 1.

Crowman
  • 25,242
  • 5
  • 48
  • 56