Kodeco Forums

Swift Functional Programming Tutorial

Learn how to program in Swift using functional programming techniques, such as map and reduce, in this Swift functional programming tutorial.


This is a companion discussion topic for the original entry at https://www.raywenderlich.com/2273-swift-functional-programming-tutorial

Hi Colin,

First off, thanks for the tutorial. This is a very nice explanation of the concept and great examples.

I want to know the solution of the 3141 string to int though. I can’t figure out how to return an int from the function. Here is what I have:

let stringToInt = Array([β€œ3”, β€œ1”, β€œ4”, β€œ1”])
.reduce(β€œβ€) { (first, next) in first + next }

print(Int(stringToInt))

Thanks very much.
Kevin

Here’s buildIndex in Swift 2.0

func buildIndex(words: [String]) -> [Entry] {
    var result = [Entry]()
    
    var letters = [Character]()
    for word in words {
        let firstLetter = Character(word.substringToIndex(word.startIndex.advancedBy(1)).uppercaseString)
        
        if !letters.contains(firstLetter) {
            letters.append(firstLetter)
        }
    }
    
    for letter in letters {
        var wordsForLetter = [String]()
        for word in words {
            let firstLetter = Character(word.substringToIndex(word.startIndex.advancedBy(1)).uppercaseString)
            
            if firstLetter == letter {
                wordsForLetter.append(word)
            }
        }
        result.append((letter, wordsForLetter))
    }
    return result
}

Colin, Thank you for the tutorial. I am a big fan of functional programming. Ocaml was my language of choice in the past. It’s been over 10 years since I have even thought about it. Your tutorial reintroduced it to me for Swift.
It’s a fun and thought provoking style of programming.

Here’s the build using the Swiftz library found on GitHub.

import Swiftz
extension String {
    func firstCharacterUpcase () -> Character {
        return Character(self.substringToIndex(self.startIndex.advancedBy(1)).uppercaseString)
    }
}

func buildIndexSwiftz(words:[String]) -> [Entry] {
    return words.reverse()
        .reduce([:] , combine: { $0.insertWith($1.firstCharacterUpcase(), v: [$1], combiner: (+)) } )
        .reduce([]  , combine: { $0.cons( ($1.0,$1.1) ) } )
        .sort({$0.0 <= $1.0})
}

Some notes

  1. The extension to the string is simply for readability in the final function
  2. process: reverse the array, process the words into a Dictionary of type [Character:[String], convert the dictionary into [Entry], then sort it based on the first in the tuple.
  3. I reverse the array so that the results match the order of the original imperative style. This is covering the difference between appending to an array and cons’ing an array.

let digits = [β€œ3”,β€œ1”,β€œ4”,β€œ1”]
let digitNum = digits.reduce(0, combine: { (total, digit) in total*10 + Int(digit)! } )
print(digitNum)

Great article.

For the last challenge this is what I did:

I added this code before the return:

let sortedWords = words.sorted{
$0.localizedCaseInsensitiveCompare($1) == ComparisonResult.orderedAscending
}

And off course changed the first line of the return to this:

return distinct(source: sortedWords.map(firstLetter))

Is that right?

Worked for me. Good job!

(P.S. I worked through this whole exercise while converting it to Swift 3 … a bit of a challenge :smiley: )

Great Article!

3141 example
let digits = [β€œ3”,β€œ1”,β€œ4”,β€œ1”]
let tot = digits.reduce(0) { (total, digit) in total * 10 + Int(digit)!}
tot

worked like a charm!

Thanks a lot for this great article. I was learning this with Swift 4.
The functions as modified for Swift 4.0 (function distinct generic changed to Comparable from Equatable and return collection sorted for the last challenge):

func distinct<T: Comparable>(_ source: [T]) -> [T] {
	var unique = [T]()
	for item in source {
		if !unique.contains(item) {
			unique.append(item)
		}
	}
	return unique.sorted(by: <)
}

func buildIndex(words: [String]) -> [Entry] {
	func firstLetter(_ str: String) -> Character {
		return Character((str as NSString).substring(to: 1).uppercased())
	}
		
	return distinct(words.map(firstLetter)).map { (letter) -> Entry in
		return (letter, words.filter { (word) -> Bool in
			firstLetter(word) == letter
		})
	}
}

This tutorial is more than six months old, so questions are no longer supported at the moment for it. We will update it as soon as possible. Thank you! :]