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

Swift, functional programming, and the future of Objective-C

Swift, functional programming, and the future of Objective-C

I gave this talk at NSMeetup in San Francisco, shortly after the Swift language was announced. It points out the language's many roots in functional programming languages, and considers what this means.

Time has marched onwards. If you want to hear about Swift from an FP perspective, there are now entire books in it!

Presented at NSMeetup in San Francisco on 2014-07-02

Alexis Gallagher

July 02, 2014
Tweet

More Decks by Alexis Gallagher

Other Decks in Technology

Transcript

  1. Swift,
    functional programming,
    & the future of Objective-C
    Alexis Gallagher
    @alexisgallagher
    Part of a talk delivered on 2014-07-02

    View full-size slide

  2. Ques%ons
    1. What's)new)in)Swi.?
    2. Is)Swi.)a)func5onal)programming)language?
    • And)what)is)"func5onal",)anyway?)Who)cares?
    3. Is)ObjC)going)away?
    • And)so,)is)everything)easier)now?

    View full-size slide

  3. What's'hardly'new'in'Swi,?

    View full-size slide

  4. Objective-C
    • classes
    • methods
    • protocols
    • categories
    • functions
    • ARC
    • blocks
    • Cocoa values 

    & collections

    View full-size slide

  5. Objective-C
    Swift
    • classes
    • methods
    • protocols
    • extensions
    • functions
    • ARC
    • closures
    • Cocoa values 

    & collections

    View full-size slide

  6. just%syntax,%almost
    ObjC:
    // Foo.h
    @interface Foo : UIView
    @property (nonatomic,weak) UIView * myView
    @end
    @implementation Foo
    - (CGFloat) addAtX:(CGFloat) x andY:(CGFloat) y {
    UIView * v = [[UIView alloc] initWithFrame:CGRectMake(x,y,10,10)];
    [self addSubview:v];
    self.myView = v;
    return x + y;
    }
    @end

    View full-size slide

  7. just%syntax,%almost
    Swi$:
    class Foo: UIView {
    weak var myView:UIView?
    func addAt(#x:CGFloat, y:CGFloat) -> CGFloat {
    let v = UIView(frame:CGRectMake(x,y,10,10))
    self.addSubview(v)
    self.myView = v
    return x + y
    }
    }

    View full-size slide

  8. blocks'(closures)
    ObjC:
    NSInteger (^increment)(NSInteger) = ^NSInteger (NSInteger x) {
    return x+1;
    }
    Swi$:
    let increment = {
    (x:NSInteger) -> NSInteger in
    return x+1
    }

    View full-size slide

  9. What's'a'bit$new'in'Swi,?

    View full-size slide

  10. Objective-C
    • structs
    • namespaces
    • operator
    overloading
    • ObjC interop
    • Swift values &
    collections
    Swift
    +
    Swift
    • classes
    • methods
    • protocols
    • extensions
    • functions
    • ARC
    • closures
    • Cocoa values 

    & collections

    View full-size slide

  11. structs&are&peers&to&classes
    ObjC:
    CGRect r = [view frame];
    CGFloat intTopY = CGRectGetMinY(CGRectIntegral(r));
    Swi$:
    extension CGRect {
    func intTopY() -> CGFloat {
    return CGRectGetMinY(CGRectIntegral(self))
    }
    }
    let r = view.frame;
    let intTopY = r.intTopY;

    View full-size slide

  12. What's'really&new'in'Swi,?

    View full-size slide

  13. Objective-C
    • enums with associated values
    • option types
    • pattern matching
    • generics
    • type inference
    • immutability supports
    • tuples
    Swift
    +
    • structs
    • namespaces
    • operator
    overloading
    • ObjC interop
    • Swift values &
    collections
    Swift
    +
    Swift
    • classes
    • methods
    • protocols
    • extensions
    • functions
    • ARC
    • closures
    • Cocoa values 

    & collections

    View full-size slide

  14. Objective-C
    • enums with associated values
    • option types
    • pattern matching
    • generics
    • type inference
    • immutability supports
    • tuples
    Swift
    +
    • structs
    • namespaces
    • operator
    overloading
    • ObjC interop
    • Swift values &
    collections
    Swift
    +
    Swift
    • classes
    • methods
    • protocols
    • extensions
    • functions
    • ARC
    • closures
    • Cocoa values 

    & collections

    View full-size slide

  15. Every “really new” part of Swift
    originated in a functional programming
    language of the 1980s or earlier.

    View full-size slide

  16. No#ma&er#what#language#you#work#
    in,#programming#in#a#func7onal#style#
    provides#benefits.#You#should#do#it#
    whenever#it#is#convenient....
    —"John"Carmack,"2012.

    View full-size slide

  17. JavaScript*is*brilliant*and*is*
    succeeding*...*and*I*think*it's*because*
    of*the*func:onal*stuff.
    —"Douglas"Crockford,"2014

    View full-size slide

  18. a"programming"style
    trea%ng(the
    func%on
    as#the#primary#unit#of#abstrac2on

    View full-size slide

  19. t0 = 5
    f(t0) = 50
    NSNumber * t0 = @5;
    NSNumber * pos = f(t0);
    pos; // => 50
    f(t0) = 50 pos = f(t0);
    pos; //=> 100; (surprise!)
    computational functions

    do things
    mathematical functions
    establish true relations
    which remain true

    View full-size slide

  20. mathematical variables
    are names
    we give to values
    t0 = 5
    t0 = 5
    t0 = 6
    computational variables
    are like names for places,
    whose contents can change
    NSNumber * five = @5;
    five = @6; // ?!
    five = @7;
    [five setIntegerValue:8]; // ?! ?!

    View full-size slide

  21. FP style boils down to
    • Restrictions to emulate the
    predictability of mathematical
    functions and variables
    • Idioms to use functions for all
    abstraction — in defining other
    functions, in hiding information, etc.
    • (Sometimes) type systems to
    provide compile-time checks on the
    values moving through functions

    View full-size slide

  22. • purity and immutability guarantees


    • function literals
    • function closures
    • functions as first-class values

    • enums (aka, sum types, tagged unions)
    • algebraic data types
    • type inference
    • fancy types: first-order, recursive, 

    dependent, higher-kinded, constrained, 

    etc..
    FEATURES
    • Idioms
    • combine, pass, & return

    functions like other values
    • Restrictions
    • pure functions
    • immutable data
    • Type systems (sometimes)
    • to check valid values
    STYLE supported by

    View full-size slide

  23. Haskell (1988)
    Scheme (1975)
    SML (1984)
    ML (1973)
    Scala (2003)
    OCaml (1996)
    Clojure (2009)
    F# (2005)
    Erlang (1986)
    dynamic static
    Coq, Agda, Idris

    View full-size slide

  24. So is Swift “functional”?

    View full-size slide

  25. Haskell SML Scheme Clojure Swift ObjC
    purity & immutability help Yes, very. Y Y Y Y meh
    function literals, closures,
    first-classness
    Y Y Y Y Y meh
    expression-oriented Y Y Y Y N N
    proper tail calls Y Y Y N ? ?
    memory management Y Y Y Y meh meh
    generics Y Y N N Y N
    enum types Y Y N N Y N
    type inference Y Y N N Y N
    algebraic data types Y Y N N ? N
    super DUPER fancy types Y ? N N N N

    View full-size slide

  26. If this were 1998 

    Swift would be a
    niche functional language

    View full-size slide

  27. If this were 1998 

    Swift would be a
    niche functional language
    … but maybe we’re all functional now? or could be?

    View full-size slide

  28. Should we care?

    View full-size slide

  29. functional Swift: 

    (embarrassingly trivial) HOFs

    View full-size slide

  30. Higher'order*func/ons:*filter
    ObjC:
    NSArray * inArray = @[@"Hello",@"Ciao"];
    NSArray * outArray = [inArray filteredArrayUsingPredicate:
    [NSPredicate predicateWithBlock:
    ^BOOL(NSString * item, NSDictionary *bindings) {
    return [item hasPrefix:@"Hello"];
    }]];
    Swi$:
    let inArray = ["Hello","Ciao"];
    let outArray = inputArray.filter({ $0.hasPrefix("Hello") })

    View full-size slide

  31. Higher'order*func/ons:*map
    ObjC:
    NSArray * inArray = @[@"John Appleseed", @"Sally Appleseed"];
    NSMutableArray * outArray = [NSMutableArray array];
    for (NSString * name in inArray) {
    [outArray addObject:[name componentsSeparatedByString:@" "][0]];
    }
    Swi$:
    let inArray = ["John Appleseed", "Sally Appleseed"];
    let outArray = inArray.map({ $0.componentsSeparatedByString(" ")[0] })

    View full-size slide

  32. Higher'order*func/ons:*reduce
    reduce!is!a!HOF!for!processing!a!collec1on!into!a!single!value.
    Swi$:
    let x = [1,2,3,4]
    let sum = x.reduce(0, +);
    sum // => 7
    let product = x.reduce(1, *);
    product //=> 24

    View full-size slide

  33. Closures: variable capture on purpose
    func makeCounter() -> (() -> NSInteger) {
    var x = 0
    func increment() -> NSInteger {
    x = x + 1;
    return x;
    }
    return increment;
    }
    var counter1 = makeCounter()
    var counter2 = makeCounter()
    counter1() //=> 1
    counter1() //=> 2
    counter1() //=> 3
    counter2() //=> 1

    View full-size slide

  34. functional Swift: 

    JSON as ADT

    View full-size slide

  35. JSON
    NSJSONSerialization Class Reference

    An object that may be converted to JSON must have the following
    properties:
    •The top level object is an NSArray or NSDictionary.
    •All objects are instances of NSString, NSNumber, NSArray,
    NSDictionary, or NSNull.
    •All dictionary keys are instances of NSString.
    •Numbers are not NaN or infinity.
    Other rules may apply. Calling isValidJSONObject: or attempting a
    conversion are the definitive ways to tell if a given object can be
    converted to JSON data.

    View full-size slide

  36. JSON%as%algebraic%data%type
    Enumera(on*with*associated*values
    enum JSONValue {
    case JNumber(NSNumber)
    case JString(String)
    case JBool(Bool)
    case JNull
    case JArray(Array)
    case JObject(Dictionary)
    case JInvalid(NSError)
    // ...
    }
    Source:(h*ps:/
    /github.com/lingoer/Swi7yJSON

    View full-size slide

  37. functional Swift: 

    Improving on NSError

    View full-size slide

  38. NSError&is&ugly
    ObjC:
    NSError *error;
    NSData *data = [NSData dataWithContentsOfFile:file options:0 error:&error];
    if(data == nil) {
    // handle error
    }

    View full-size slide

  39. Either'type
    Swi$:
    enum DataResult {
    case Success(NSData)
    case Error(NSError)
    // ...
    }
    switch NSData(contentsOfFile:file, options:0) {
    case .Success(let data):
    // handle data here then return
    case .Error(let error):
    // handle error here then return
    }

    View full-size slide

  40. SwiftZ (by maxpow4h)
    Either and Result:
    // Result represents something that could work or be an NSError.
    // Say we have 2 functions, the first fetches from a web services,
    // the second decodes the string into a User.
    // Both *could* fail with an NSError, so we use a Result.
    func getWeb() -> Result {
    var e: NSError?
    let str = doStuff("foo", e)
    return Result(e, str)
    }
    func decodeWeb(str: String) -> Result {
    var e: NSError?
    let user = decode(str, e)
    return Result(e, user)
    }
    // We can compose these two functions with the `>>=` function.
    let getUser: Result = getWeb() >>= decodeWeb
    switch (getUser) {
    case let .Error(e): println("NSError: \(e)")
    case let .Value(user): println(user.name)

    View full-size slide

  41. Is ObjC going away? 

    Is it “easier” now?

    View full-size slide

  42. Objective-C
    • enums with associated values
    • option types
    • pattern matching
    • generics
    • type inference
    • immutability supports
    • tuples
    Swift
    +
    • structs
    • namespaces
    • operator
    overloading
    • ObjC interop
    • Swift values &
    collections
    Swift
    +
    Swift
    • classes
    • methods
    • protocols
    • extensions
    • functions
    • ARC
    • closures
    • Cocoa values 

    & collections

    View full-size slide

  43. –"Advanced Swift Debugging in LLDB", WWDC2014, session 410, 20m—28m.
    “Objective-C isn't really going anywhere.... Even if you start a
    brand new Swift app for the first time today after this session,
    you're going to use Cocoa, or Cocoa Touch. You're going to
    import Foundation. You're going to import UIKit. Those
    frameworks are written in Objective-C. That means, wherever you
    look around, there's going to be Objective-C in the picture.
    And you're going to have to deal with debugging mixed Swift /
    Objective-C situations..”

    View full-size slide

  44. Canaries in the ObjC coal mine
    • Swift achieves genuine C-like performance
    • Swift-only types appearing at public API boundaries
    • Deprecation of the ObjC runtime’s more dynamic features

    View full-size slide

  45. • GitHub RAC devs (jspahrsummers, joshaber, & others)
    • ReactiveCocoa. This work is indirectly influenced by typed FP.


    • Maxwell Swadling
    • SwiftZ. Currently translating lots of typed FP idioms into a Swift library. 


    • David Nolen.
    • Om. Functional approach to writing GUIs in the browser, using ClojureScript with
    Facebook’s React, leveraging CSP-style concurrency. Untyped FP.


    • Upcoming book from ObjC.io authors.

    View full-size slide

  46. • Videos, notes, and exercises from the Coursera “Programming
    Languages” course, a great intro to Scheme, SML, and Ruby.


    • Interesting way to do SICP: http://understudyapp.com
    • The talks by Rich Hickey (inventor of Clojure) are very rich

    View full-size slide