Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Swift Functional Programming

Secret Lab
February 02, 2016

Swift Functional Programming

Overview of the basics of Functional Programming using the Swift programming language. Presented at the Functional Programming Miniconf at Linux.conf.au 2016, in Geelong.

Secret Lab

February 02, 2016
Tweet

More Decks by Secret Lab

Other Decks in Programming

Transcript

  1. Agenda • What is Swift • Why bother? • Installing

    Swift • Playgrounds/REPL • Functional Programming Fundamentals • Swift Functional Programming
  2. Swift?! • Similar to Rust, Perl 6, and a bunch

    of other languages… • Another trendy, hip, cool, modern programming language… • Actually pretty good…
  3. $ sudo apt-get install clang libicu-dev Download a binary from

    https://swift.org/download/#linux; extract it $ tar xzf swift-<VERSION>-<PLATFORM>.tar.gz $ export PATH=/path/to/usr/bin:"${PATH}" This creates a usr/ directory; add it to your path: Swift is now installed! Download the pre-requisites:
  4. $ swift Welcome to Apple Swift version 2.1.1 (swiftlang-700.1.101.15 clang-700.1.81).

    Type :help for assistance. 1> let text = "Don t worry if you are not computer" text: String = "Don t worry if you are not computer" 2> text.uppercaseString $R0: String = "DON T WORRY IF YOU ARE NOT COMPUTER" 3>
  5. –John Carmack “No matter what language you work in, programming

    in a functional style provides benefits. You should do it whenever it is convenient, and you should think hard about the decision when it isn't convenient.”
  6. func add(num1: Int, _ num2 : Int) -> Int {

    return num1 + num2 } var addNumbers : (Int,Int) -> Int
  7. func add(num1: Int, _ num2 : Int) -> Int {

    return num1 + num2 } var addNumbers : (Int,Int) -> Int addNumbers = add
  8. func add(num1: Int, _ num2 : Int) -> Int {

    return num1 + num2 } var addNumbers : (Int,Int) -> Int addNumbers = add addNumbers(1,2)
  9. var add = { (num1 : Int, num2 : Int)

    -> Int in return num1 + num2 }
  10. var add = { (num1 : Int, num2 : Int)

    -> Int in return num1 + num2 }
  11. var add = { (num1 : Int, num2 : Int)

    -> Int in return num1 + num2 }
  12. var add = { (num1 : Int, num2 : Int)

    -> Int in return num1 + num2 }
  13. typealias Adder = (Int) -> Int func makeAdder(number: Int) ->

    Adder { return { $0 + number } } let addTwo = makeAdder(2)
  14. typealias Adder = (Int) -> Int func makeAdder(number: Int) ->

    Adder { return { $0 + number } } let addTwo = makeAdder(2) addTwo(5) // 7
  15. typealias TwoIntegerFunction = (Int,Int) -> Int func applyOperationToNumbers(num1 : Int,

    _ num2 : Int, operation: TwoIntegerFunction) -> Int { return operation(num1, num2) }
  16. typealias TwoIntegerFunction = (Int,Int) -> Int func applyOperationToNumbers(num1 : Int,

    _ num2 : Int, operation: TwoIntegerFunction) -> Int { return operation(num1, num2) } let add : TwoIntegerFunction = { $0 + $1 }
  17. typealias TwoIntegerFunction = (Int,Int) -> Int func applyOperationToNumbers(num1 : Int,

    _ num2 : Int, operation: TwoIntegerFunction) -> Int { return operation(num1, num2) } let add : TwoIntegerFunction = { $0 + $1 } applyOperationToNumbers(2, 3, operation: add)
  18. typealias TwoIntegerFunction = (Int,Int) -> Int func applyOperationToNumbers(num1 : Int,

    _ num2 : Int, operation: TwoIntegerFunction) -> Int { return operation(num1, num2) } let add : TwoIntegerFunction = { $0 + $1 } applyOperationToNumbers(2, 3, operation: add) applyOperationToNumbers(2, 3, operation: +)
  19. var text = "As you might know, I am a

    full time Internet" text.uppercaseString // "AS YOU MIGHT KNOW, I AM A FULL TIME INTERNET"
  20. func incrementArray(theArray: [Int]) -> [Int] { var result: [Int] =

    [] for item in theArray { result.append(item+1) } return result }
  21. func doubleArray(theArray: [Int]) -> [Int] { var result: [Int] =

    [] for item in theArray { result.append(item*2) } return result }
  22. typealias TransformFunction = Int -> Int func manipulateArray(theArray: [Int], transform:

    TransformFunction) -> [Int] { var result: [Int] = [] for item in theArray { result.append(transform(item)) } return result }
  23. [ ] , , , Int Int Int Int [

    ] , , , Int Int Int Int
  24. [ ] , , , Int Int Int Int [

    ] , , , ? Bool Bool Bool Bool
  25. func manipulateArray(theArray: [Int], transform: TransformFunction) -> [Int] { var result:

    [Int] = [] for item in theArray { result.append(transform(item)) } return result }
  26. func map<T>(xs: [Int], transform: Int->T) -> [T] { var result:

    [T] = [] for x in xs { result.append(transform(x)) } return result }
  27. func map<T>(xs: [Int], transform: Int->T) -> [T] { var result:

    [T] = [] for x in xs { result.append(transform(x)) } return result }
  28. func map<Element, T>(xs: [Element], transform: Element->T) -> [T] { var

    result: [T] = [] for x in xs { result.append(transform(x)) } return result }
  29. extension Array { func map<T>(transform: (Element) -> T) -> [T]

    { var result: [T] = [] for x in self { result.append(transform(x)) } return result } }
  30. Map actually comes with Swift Hopefully you were expecting me

    to say that… … the point is, there’s no secrets to Map!
  31. // Compose a function from two functions func compose<T>(funcA: T->T,

    _ funcB: T->T) -> T->T { // Return a new function that calls them both return { funcB(funcA($0)) } }
  32. // Compose a function from two functions func compose<T>(funcA: T->T,

    _ funcB: T->T) -> T->T { // Return a new function that calls them both return { funcB(funcA($0)) } } // Two dumb lil functions let double = { $0 * 2 } let addOne = { $0 + 1 }
  33. // Compose a function from two functions func compose<T>(funcA: T->T,

    _ funcB: T->T) -> T->T { // Return a new function that calls them both return { funcB(funcA($0)) } } // Two dumb lil functions let double = { $0 * 2 } let addOne = { $0 + 1 } // Compose 'em! let doubleAndAddOne = compose(double, addOne)
  34. // Compose a function from two functions func compose<T>(funcA: T->T,

    _ funcB: T->T) -> T->T { // Return a new function that calls them both return { funcB(funcA($0)) } } // Two dumb lil functions let double = { $0 * 2 } let addOne = { $0 + 1 } // Compose 'em! let doubleAndAddOne = compose(double, addOne) doubleAndAddOne(5)
  35. func compose<T>(funcA: T->T, _ funcB: T->T) -> T->T These have

    to be the same type, for no good reason!
  36. func compose<T,U,V>(funcA: T->U, _ funcB: U->V) -> T->V { return

    { funcB(funcA($0)) } } let isEven = { $0 % 2 == 0 } // Int -> Bool let flipBool = { !$0 } // Bool -> Bool let isNotEven = compose(isEven, flipBool) // Int -> Bool isNotEven(4) // false
  37. import struct Swiftz.List // Cycles a finite list of numbers

    into an infinite list. let finite : List<UInt> = [1, 2, 3, 4, 5] let infiniteCycle = finite.cycle() // Lists also support the standard map, filter, and reduce operators. let l : List<Int> = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] let twoToEleven = l.map(+1) // [2, 3, 4, 5, 6, 7, 8, 9, 10, 11] let even = l.filter((==0) • (%2)) // [2, 4, 6, 8, 10] let sum = l.reduce(curry(+), initial: 0) // 55 // Plus a few more. let partialSums = l.scanl(curry(+), initial: 0) // [0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55] let firstHalf = l.take(5) // [1, 2, 3, 4, 5] let lastHalf = l.drop(5) // [6, 7, 8, 9, 10]
  38. Learning more • Learn You a Haskell for Great Good!

    • Pearls of Functional Algorithm Design • Programming in Haskell (Hutton) • Apple’s Swift Book(s) • IBM Swift Resources: https://developer.ibm.com/swift/