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

4b71cdf53bc76edd1a2ab66c446954b5?s=128

Alexis Gallagher

July 02, 2014
Tweet

Transcript

  1. 1.

    Swift, functional programming, & the future of Objective-C Alexis Gallagher

    @alexisgallagher Part of a talk delivered on 2014-07-02
  2. 4.

    Objective-C • classes • methods • protocols • categories •

    functions • ARC • blocks • Cocoa values 
 & collections
  3. 5.

    Objective-C Swift • classes • methods • protocols • extensions

    • functions • ARC • closures • Cocoa values 
 & collections
  4. 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
  5. 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 } }
  6. 8.

    blocks'(closures) ObjC: NSInteger (^increment)(NSInteger) = ^NSInteger (NSInteger x) { return

    x+1; } Swi$: let increment = { (x:NSInteger) -> NSInteger in return x+1 }
  7. 10.

    Objective-C • structs • namespaces • operator overloading • ObjC

    interop • Swift values & collections Swift + Swift • classes • methods • protocols • extensions • functions • ARC • closures • Cocoa values 
 & collections
  8. 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;
  9. 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
  10. 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
  11. 15.

    Every “really new” part of Swift originated in a functional

    programming language of the 1980s or earlier.
  12. 16.

    FP

  13. 20.

    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
  14. 21.

    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]; // ?! ?!
  15. 22.

    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
  16. 23.

    • 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
  17. 24.

    Haskell (1988) Scheme (1975) SML (1984) ML (1973) Scala (2003)

    OCaml (1996) Clojure (2009) F# (2005) Erlang (1986) dynamic static Coq, Agda, Idris
  18. 26.

    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
  19. 28.

    If this were 1998 
 Swift would be a niche

    functional language … but maybe we’re all functional now? or could be?
  20. 31.

    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") })
  21. 32.

    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] })
  22. 34.

    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
  23. 36.

    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.
  24. 37.

    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<JSONValue>) case JObject(Dictionary<String,JSONValue>) case JInvalid(NSError) // ... } Source:(h*ps:/ /github.com/lingoer/Swi7yJSON
  25. 40.

    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 }
  26. 41.

    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<A>. func getWeb() -> Result<String> { var e: NSError? let str = doStuff("foo", e) return Result(e, str) } func decodeWeb(str: String) -> Result<User> { var e: NSError? let user = decode(str, e) return Result(e, user) } // We can compose these two functions with the `>>=` function. let getUser: Result<User> = getWeb() >>= decodeWeb switch (getUser) { case let .Error(e): println("NSError: \(e)") case let .Value(user): println(user.name)
  27. 43.

    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
  28. 44.

    –"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..”
  29. 45.

    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
  30. 46.

    • GitHub RAC devs (jspahrsummers, joshaber, & others) • ReactiveCocoa.

    This work is indirectly influenced by typed FP.
 <https://github.com/ReactiveCocoa/ReactiveCocoa> • Maxwell Swadling • SwiftZ. Currently translating lots of typed FP idioms into a Swift library. 
 <https://github.com/maxpow4h/swiftz> • David Nolen. • Om. Functional approach to writing GUIs in the browser, using ClojureScript with Facebook’s React, leveraging CSP-style concurrency. Untyped FP.
 <http://swannodette.github.io/2013/12/17/the-future-of-javascript-mvcs/> • Upcoming book from ObjC.io authors.
  31. 47.
  32. 48.
  33. 49.

    • Videos, notes, and exercises from the Coursera “Programming Languages”

    course, a great intro to Scheme, SML, and Ruby.
 <https://class.coursera.org/proglang-2012-001> • Interesting way to do SICP: http://understudyapp.com • The talks by Rich Hickey (inventor of Clojure) are very rich