# Always write a generalized version of your algorithm

Suppose you want to find the minimum value in an array. Well, the Swift standard library has you covered:

```let a = [6, 2, 4, 7, 8, 10]
minElement(a)  // returns 2
```

Ok that’s cool. But suppose you have an array of strings of integers and you want the minimum numeric value.

Well, I guess you could map them to `Int` and then use the same function:

```let a = ["6", "2", "4", "7", "8", "10"]
minElement( a.map { \$0.toInt() })
```

Nope, compiler error. `String.toInt` returns an `Int?`, because maybe the string isn’t a number.

Fair enough. I happen to know with my intimate knowledge of the problem domain that we can just ignore non-numeric values. So maybe filter those out?

```minElement( a.map { \$0.toInt() }.filter { \$0 != nil } )  // hmmm
```

Nope, more compiler errors, because now we have only non-`nil` values, but they’re still optionals and an `Int?` doesn’t conform to `Comparable`. So maybe another `map` to force-unwrap the results (force unwrap is OK because the filter will guarantee no non-nil elements):1

```minElement( a.map{ \$0.toInt() }.filter { \$0 != nil }.map { \$0! } )  // yuck
```

Ok that compiles now and does return the minimum numeric value. But what if we wanted the result to still be a string?

```"\(minElement( a.map{ \$0.toInt() }.filter { \$0 != nil }.map { \$0! } ))" // bleurgh
```

That’s pretty horrible, and at this point I’m thinking of registering GiveUpAndUseAforLoop.com,2 and Marco Arment is yelling at you kids with your new language to get off his lawn.

Really, what we need is for `minElement` to take a predicate instead of only using the default <. It doesn't (mutter, grumble) but if it did, we could write this:

```minElement(a) {
switch (\$0.toInt(), \$1.toInt()) {
case (_, nil): return true
case (nil, _): return false
case (let i, let j): return i < j
}
}
```

Ahh. Faith in the functional programming style restored.3 This takes each element, checks if the `toInt()` of either is `nil` using pattern matching, always preferring the non-`nil` version, and if neither are, compares them. Since all it's doing is comparing the converted value, not returning one, the minimum returned is a string.4

There's nothing stopping you from implementing your own overload of Apple's `minElement` that takes a predicate:5

```func minElement
<E, R: Sequence
where E == R.GeneratorType.Element>
(range: R, pred: (E,E)->Bool) -> E {

var gen = range.generate()
var min_so_far = gen.next()!

while let next = gen.next() {
if(pred(next,min_so_far)) {
min_so_far = next
}
}

return min_so_far
}
```

This version copies the Swift library version's questionable practice of exploding in flames if you pass it an empty sequence – the (better?) alternative being make the return value optional to force the caller to acknowledge this possibility.

The moral here is that if you ever write a high-order function, write it as generally as possible. It's only a few extra lines to declare the common case using the general case:6

```func minElement
<E: Comparable, R: Sequence
where E == R.GeneratorType.Element>
(range: R) -> E {
return myMinElement(range, <)
}
```

Apple does this for most functions (such as `sort`), just not `minElement`. But then it is only beta 3, hang in there.

1. “I thought it was guaranteed not to be nil at this point” is what you could write to the log file in the outer exception handler you can’t have.
2. Just kidding, I didn’t think about it, I registered it straight away.
3. This code would be even neater if the Swift `switch` statement would implicitly return the values of single-line cases, i.e. if all the returns in that closure were removed, the switch would evaluate to the value of the selected case statement, and the closure would return it. They closed my radar as a dupe of 16169366 (don't file another duplicate though).
4. It's still not perfect – if none of the elements are numeric, it'll return the first one. Also, it'll convert each element twice. Hold that thought for a later post though.
5. Actually, there might be some compiler bugs stopping you, but I'll leave you to discover those on your own.
6. If the language would let you, you could even default the last parameter to <, but it won't, so you can't. More dynamic default arguments (including ones derived from other arguments to the same function) could be pretty useful in cutting down the amount of code you need to write for these general- and special-case versions.

## One thought on “Always write a generalized version of your algorithm”

1. […] my previous post on finding minimums, a couple of people pointed out that reduce would be much better suited to the […]