So a while back I wrote about using some functional programming techniques in Swift to solve the Luhn credit card checksum problem.

One of the suggestions in the article was defining and using `|`

> to avoid the annoying tennis-match bouncing left and right between free functions and methods.

Since 2.0 came out, I’ve been thinking I really needed to update some of my articles to the new syntax, and started on this one. Except as protocol extensions are the new hotness, using them would probably be the more “Swift-y” way of writing this. So here’s a solution using new 2.0 features.

As a reminder, here’s the requirements, in the form of wikipedia’s description of the algorithm:

- From the rightmost digit, which is the check digit, moving left, double the value of every second digit; if the product of this doubling operation is greater than 9 (e.g., 8 × 2 = 16), then sum the digits of the products (e.g., 16: 1 + 6 = 7, 18: 1 + 8 = 9).
- Take the sum of all the digits.
- If the total modulo 10 is equal to 0 (if the total ends in zero) then the number is valid according to the Luhn formula; else it is not valid.

So, here in turn are each of the components, all written as extensions.

First, converting characters to integers. Similar to `String.toInteger`

becoming `Int.init(String)`

, here’s an extension of `Int`

:

extension Int { init?(c: Character) { guard let i = Int(String(c)) else { return nil } self = i } }

Here I’m using `guard`

to check the value is convertible and return `nil`

if not. Yes, I know, this is hardly different from an `if let/else`

, but I like the use of `guard`

whenever I want to handle a failure case like this “up front”.

It would be nice to make this a protocol extension rather than an extension of `Int`

. All the std lib integer types support a from-string initializer, after all. But this would involve creating a protocol like `IntegerStringConvertible`

and then extending all the integers to conform to it, since such a common grouping doesn’t exist.

The previous post defined `mapSome`

, which takes a transformation function that returns an optional, and returns an array of only those values that weren’t transformed into `nil`

:

extension SequenceType { func mapSome<U>(transform: Generator.Element -> U?) -> [U] { var result: [U] = [] for case let x? in lazy(self).map(transform) { result.append(x) } return result } }

(the `for case let x?`

is using the new pattern-matching syntax that lets you `for`

over only the non-nil values in a sequence)

But as of 2.0, `flatMap`

has been enhanced to do this exact thing. So we no longer need to define it.

We’re going to use this along with the character-to-integer initializer to extract only the numbers from the credit-card string, like so, using the new 2.0b2 feature of using an `init`

as a function:

":123-456:".characters.flatMap(Int.init) // returns [1,2,3,4,5,6]

(note, we have to do this on the `.characters`

view now, since `String`

is no longer itself a sequence).

Next, the a function that let you apply a transformation only to every *n* th value in a sequence:

extension SequenceType { func mapEveryNth(n: Int, transform: Generator.Element -> Generator.Element) -> [Generator.Element] { // enumerate starts from zero, so for this to work with the nth element, // and not the 0th, n+1th etc, we need to add 1 to the ifIndex check: let isNth = { ($0 + 1) % n == 0 } return enumerate().map { i, x in isNth(i) ? transform(x) : x } } }

Then, a `sum`

on any sequence that contains integers:

extension SequenceType where Generator.Element: IntegerType { func sum() -> Generator.Element { return reduce(0, combine: +) } }

and an extension on any integer to check if it’s a multiple of another:

extension IntegerType { func isMultipleOf(of: Self) -> Bool { return self % of == 0 } }

And finally, to put them all together into a single extension to `String`

that validates the checksum:

extension String { func luhnchecksum() -> Bool { return characters .flatMap(Int.init) .reverse() .mapEveryNth(2) { $0 < 5 ? $0*2 : $0*2 - 9 } .sum() .isMultipleOf(10) } } let ccnum = "4012 8888 8888 1881" print( ccnum.luhnchecksum() ? "👍" : "👎" )

This now looks very similar to the version that used the `|`

> operator – but without having to define any custom operator at all. Which feels like a win to me.

Yes, you could have done all this before using extensions of concrete objects in 1.2. But most of these extensions are more general than that – for example, `mapSome`

can work on the string character view, but also arrays, dictionaries, sets.

Anyway, now back to playing with beta 2…