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

Post on 27-Aug-2014

1.669 views 1 download

Tags:

description

Slides supporting a talk on Swift and functional programming. These are not entirely free-standing, alas. Just come to the next talk! :)

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

Swift, functional programming,

& the future of Objective-C

Alexis Gallagher @alexisgallagherPart of a talk delivered on 2014-07-02

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?

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

Objective-C

• classes • methods • protocols • categories • functions • ARC • blocks • Cocoa values

& collections

Objective-C

Swift

• classes • methods • protocols • extensions • functions • ARC • closures • Cocoa values

& collections

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

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 }}

blocks'(closures)

ObjC:

NSInteger (^increment)(NSInteger) = ^NSInteger (NSInteger x) { return x+1;}

Swi$:

let increment = { (x:NSInteger) -> NSInteger in return x+1}

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

Objective-C

• structs • namespaces • operator

overloading • ObjC interop • Swift values &

collections

Swift+Swift

• classes • methods • protocols • extensions • functions • ARC • closures • Cocoa values

& collections

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;

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

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

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

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

language of the 1980s or earlier.

FP

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.

JavaScript*is*brilliant*and*is*succeeding*...*and*I*think*it's*because*

of*the*func:onal*stuff.—"Douglas"Crockford,"2014

a"programming"styletrea%ng(the

func%onas#the#primary#unit#of#abstrac2on

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

mathematical variables"are names we give to values

t0 = 5t0 = 5t0 = 6

computational variables"are like names for places, whose contents can change

NSNumber * five = @5;

five = @6; // ?!

five = @7;

[five setIntegerValue:8]; // ?! ?!

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

• 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

Haskell (1988)

Scheme (1975)SML (1984)ML (1973)

Scala (2003)

OCaml (1996)

Clojure (2009) F# (2005)

Erlang (1986)

dynamic static

Coq, Agda, Idris

So is Swift “functional”?

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

If this were 1998 Swift would be a

niche functional language

If this were 1998 Swift would be a

niche functional language

… but maybe we’re all functional now? or could be?

Should we care?

functional Swift: (embarrassingly trivial) HOFs

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") })

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] })

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 // => 7let product = x.reduce(1, *);product //=> 24

Closures: variable capture on purposefunc 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!

functional Swift: JSON as ADT

JSONNSJSONSerialization 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.

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

functional Swift: Improving on NSError

NSError&is&ugly

ObjC:

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

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}

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)  }  

Is ObjC going away? Is it “easier” now?

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

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

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

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

@end

• Videos, notes, and homework 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