Swi$:&New&Paradigms&for& iOS&Development - - PowerPoint PPT Presentation

swi new paradigms for ios development
SMART_READER_LITE
LIVE PREVIEW

Swi$:&New&Paradigms&for& iOS&Development - - PowerPoint PPT Presentation

Swi$:&New&Paradigms&for& iOS&Development Marc%Prud'hommeaux Indie&So)ware&Developer&/&marc@impathic.com GOTO$Conference Copenhagen,*September*25,*2014 1 Overview 1. Swi& 2. FP 3. Tweet 4. HOF 5.


slide-1
SLIDE 1

Swi$:&New&Paradigms&for& iOS&Development

Marc%Prud'hommeaux

Indie&So)ware&Developer&/&marc@impathic.com

GOTO$Conference

Copenhagen,*September*25,*2014 1
slide-2
SLIDE 2

Overview

  • 1. Swi&
  • 2. FP
  • 3. Tweet
  • 4. HOF
  • 5. Bork
  • 6. Ques:ons?
2
slide-3
SLIDE 3

Flash&Poll

  • Who%Programs?
  • Who%Programs%in%Objec4ve6C?
  • Who%Programs%in%Java/C#/C++?
  • Who%Programs%Func4onally?
  • Who%Programs%in%SwiB?
3
slide-4
SLIDE 4

Tweet!

4
slide-5
SLIDE 5 @interface Tweet : NSObject // Tweet.h @property (nonatomic, strong) NSString *username; @property (nonatomic, strong) NSString *body;
  • (instancetype)initWithUsername:(NSString *)username body:(NSString *)body;
@end @implementation Tweet // Tweet.m
  • (instancetype)initWithUsername:(NSString *)username
body:(NSString *)body { if (self = [super init]) { self.username = username; self.body = body; } return self; } @end @interface TweeterService : NSObject
  • (void)tweet:(Tweet *)tweet;
+ (TweeterService *)sharedService; @end TweeterService *service = [TweeterService sharedService]; Tweet *tweet = [[Tweet alloc] initWithUsername:@"gotocph" body:@"Come see my talk at GOTO!"]; [service tweet:tweet]; 5
slide-6
SLIDE 6

OBJ$C

meh 6
slide-7
SLIDE 7 struct Tweet { var username: String let body: String } class TweeterService { func tweet(tweet: Tweet) { ... } class func sharedService() -> TweeterService { ... } } let service = TweeterService.sharedService() let message = "Come see my talk at GOTO!" var tweet = Tweet(username: "gotocph", body: message) service.tweet(tweet) 7
slide-8
SLIDE 8

Swi$%&%ObjC:%The%Similari3es

  • Classes
  • Methods
  • Protocols/(interfaces)
  • Extensions/(categories)
  • Func:ons/(methods)
  • Semi=automa:c/memory/management/(ARC)
  • Closures/(blocks)
8
slide-9
SLIDE 9

Swi$:&Small&Addi,ons

  • Swi%&Structures
  • Namespaces
  • Swi%&Constants
  • Operator&Overloading
  • ObjC&Interop
9
slide-10
SLIDE 10

Swi$:&Big&Addi+ons

  • Swi%&Enumera.ons
  • Op.onals&(non5nullable&proper.es)
  • Generics
  • Type&Inference
  • Immutability&Support
  • Tuples
  • First5class&Func.ons
10
slide-11
SLIDE 11

Swi$:&Big&Addi+ons

  • Swi%&Enumera.ons
  • Op.onals&(non5nullable&proper.es)
  • Generics
  • Type&Inference
  • Immutability&Support
  • Tuples
  • First&class*Func-ons
11
slide-12
SLIDE 12 struct Tweet { var username: String let body: String } class TweeterService { func tweet(tweet: Tweet) { ... } class func sharedService() -> TweeterService { ... } } let service = TweeterService.sharedService() let message = "Come see my talk at GOTO!" var tweet = Tweet(username: "gotocph", body: message) service.tweet(tweet) 12
slide-13
SLIDE 13

Bug:%No%comple-on%no-fica-on

class TweeterService { func tweet(tweet: Tweet) { ... } } 13
slide-14
SLIDE 14

Bug:%No%comple-on%no-fica-on

class TweeterService { func tweet(tweet: Tweet) -> Void { ... } } 14
slide-15
SLIDE 15

Change'the'return'type

class TweeterService { func tweet(tweet: Tweet) -> Bool { ... } } 15
slide-16
SLIDE 16

Buzzzz!%Wrong!

class TweeterService { func tweet(tweet: Tweet) -> Bool { ... } } 16
slide-17
SLIDE 17

The$Delegate$Pa+ern$(ObjC)

@protocol TweetDelegate
  • (void)tweet:(Tweet *)tweet completed:(BOOL)successful;
@end @interface TweeterService : NSObject @property (weak) id<TweetDelegate> serviceDelegate;
  • (void)tweet:(Tweet *)tweet;
+ (TweeterService *)sharedService; @end TweeterService *service = [TweeterService sharedService]; id<TweetDelegate> delegate = [[MyTweetDelegate alloc] init]; service.serviceDelegate = delegate; [service tweet:tweet]; 17
slide-18
SLIDE 18

The$Delegate$Pa+ern$(Swi2)

protocol TweeterDeleate { func tweetCompleted(tweet: Tweet, success: Bool) } class TweeterService { var delegate: TweeterDelegate? func tweet(tweet: Tweet) { ... } class func sharedService() -> TweeterService { ... } } let service = TweeterService.sharedService() let serviceDelegate = MyTweeterDeleate() service.delegate = serviceDelegate service.tweet(tweet) 18
slide-19
SLIDE 19

FP

19
slide-20
SLIDE 20

FP

“Func&onal*Programming”

20
slide-21
SLIDE 21

FP

=>#First)Class#Func0ons

21
slide-22
SLIDE 22

Func%onal)Programming)is)a) Style

Swi$%has%many%features%that%enable%programming%in% the%Func6onal%Style

A"Func'onal"Language" compels"Func'onal" Programming

Swi$%is%not%really%a%Func2onal%Language 22
slide-23
SLIDE 23

Swi$%Closures

class TweeterService { func tweet(tweet: Tweet, done: (Bool)->Void) } 23
slide-24
SLIDE 24

The$Func)on$as$a$Data$Type

class TweeterService { func tweet(tweet: Tweet, done: (Bool)->Void) } var donefun: (Bool)->Void donefun = { success in if success { println("Tweet successful!") } else { println("Tweet failed!") } } service.tweet(tweet, done: donefun) 24
slide-25
SLIDE 25

Defining'the'Func-on'Inline

class TweeterService { func tweet(tweet: Tweet, done: (success: Bool)->Void) } service.tweet(tweet, done: { (success: Bool) in if success { println("Tweet successful!") } else { println("Fail Whale") } }) 25
slide-26
SLIDE 26

And$More$Succinctly...

class TweeterService { func tweet(tweet: Tweet, done: (success: Bool)->Void) } service.tweet(tweet) { println($0 ? "Tweet successful!" : "Fail Whale") } 26
slide-27
SLIDE 27

HOF

“Higher(Order(Func/on”

27
slide-28
SLIDE 28

MAP

FILTER REDUCE

  • h#my!
28
slide-29
SLIDE 29

MAP

Transform)some)Stuff)into)other)Stuff

FILTER

Turn%some%Stuff%into%fewer%Stuff

REDUCE

Turn%some%Stuff%into%a%single%Thing

29
slide-30
SLIDE 30

A"Danish"Tweet2

let danishTweet = Tweet(username: "Hamlet", body: "Tweets, tweets, tweets") service.tweet(danishTweet, done: { (success) -> Void in if success { println("Be") } else { println("Not to be") } }) 2"William"Shakespeare,"Hamlet,"Act"II,"Scene"2"(paraphrased) 30
slide-31
SLIDE 31 let adviceTweet = Tweet(username: "Polonius", body: "Yet here, Laertes? Aboard, aboard, for shame! " + "The wind sits in the shoulder of your sail " + "And you are stayed for. There, my blessing with thee. " + "And these few precepts in thy memory " + "Look thou character. Give thy thoughts no tongue, " + "Nor any unproportioned thought his act. " + "Be thou familiar but by no means vulgar. " + "Those friends thou hast, and their adoption tried, " + "Grapple them unto thy soul with hoops of steel, " + "But do not dull thy palm with entertainment " + "Of each new-hatched, unfledged comrade. Beware " + "Of entrance to a quarrel, but being in, " + "Bear ’t that th' opposèd may beware of thee. " + "Give every man thy ear but few thy voice. " + "Take each man’s censure but reserve thy judgment. " + "Costly thy habit as thy purse can buy, " + "But not expressed in fancy—rich, not gaudy, " + "For the apparel oft proclaims the man, " + "And they in France of the best rank and station " + "Are of a most select and generous chief in that. " + "Neither a borrower nor a lender be, " + "For loan oft loses both itself and friend, " + "And borrowing dulls the edge of husbandry. " + "This above all: to thine own self be true, " + "And it must follow, as the night the day, " + "Thou canst not then be false to any man. " + "Farewell. My blessing season this in thee.") 31
slide-32
SLIDE 32

Fail!

32
slide-33
SLIDE 33

Business'Plan:

  • 1. Localized,Tweet,Compression
  • 2. ?
  • 3. Profit!
33
slide-34
SLIDE 34

The$Problem$Domain

let charCount = countElements(tweet.body)

=="1,187"characters

countElements()-is-a-global-func3on-in-Swi6 34
slide-35
SLIDE 35

Transla'ng)the)Tweet

35
slide-36
SLIDE 36

The$Swedish$Chef

36
slide-37
SLIDE 37

Börk

37
slide-38
SLIDE 38

Børk

38
slide-39
SLIDE 39

Börk Børk

HØF

39
slide-40
SLIDE 40

Split

let words: [String] = split(tweet.body, { (c: Character) in c == " " })
  • r#just:
let words = split(tweet.body, { $0 == " " }) 40
slide-41
SLIDE 41

Words,'words,'words

words = ["Yet", "here", "Laertes?", "Aboard", "aboard", "for", "shame!", "The", "wind", "sits", "in", "the", "shoulder", "of", "your", "sail", "And", "you", "are", "stayed", "for", "There", "my", "blessing", "with", "thee", "And", "these", "few", "precepts", "in", "thy", "memory", "Look", "thou", "character", "Give", "thy", "thoughts", "no", "tongue", "Nor", "any", "unproportioned", 41
slide-42
SLIDE 42

Filter

let bigWords = words.filter({ (word: String) in countElements(word) > 7 }) More%Compactly: let bigWords = words.filter({ countElements($0) > 7 }) 42
slide-43
SLIDE 43

Map

let borks: [String] = bigWords.map({ (word: String) in "Børk" }) More%Compactly: let borks = bigWords.map({ word in "Børk" }) 43
slide-44
SLIDE 44

Reduce

let translation: String = borks.reduce("", combine: { (word1: String, word2: String) -> String in return word1 + " " + word2 }) More%Compactly: let translation = borks.reduce("", combine: { $0 + " " + $1 }) 44
slide-45
SLIDE 45

Func%on'Composi%on

let translation = split(tweet.body, { (c: Character) in c == " " }) .filter({ (word: String) in countElements(word) > 7 }) .map({ word in "Børk" }) .reduce("", combine: { $0 + " " + $1 }) let translatedTweet = Tweet(username: tweet.username, body: translation) countElements(translation) // == 125! 45
slide-46
SLIDE 46

Børk

Børk%Børk

Børk%Børk%Børk

Børk%Børk%Børk%Børk%Børk

Børk%Børk%Børk%Børk%Børk%Børk%Børk%Børk%Børk%Børk%Børk%Børk%Børk%Børk 46
slide-47
SLIDE 47

So#What?

We're%not%doing%anything%here%we%couldn't%do%in% another%other%modern%language 47
slide-48
SLIDE 48 // split the tweet into words NSMutableArray *words = [NSMutableArray array]; NSMutableString *currentWord = [NSMutableString string]; for (int i = 0, ii = tweet.body.length; i < ii; i++) { unichar currentChar = [tweet.body characterAtIndex:i]; if (currentChar == ' ') { [words addObject:currentWord]; currentWord = [NSMutableString string]; } else { [currentWord appendFormat:@"%c", currentChar]; } } // filter out the shorter words for (int j = words.count - 1; j >= 0; j--) { NSString *currentWord = words[j]; if (currentWord.length < 8) { [words removeObjectAtIndex:j]; } } // map each element of the words array to Børk for (int k = 0, kk = words.count; k < kk; k++) { words[k] = @"Børk"; } // reduce the words back into a new tweet NSMutableString *translatedTweet = [NSMutableString string]; for (int l = 0, ll = words.count; l < ll; l++) { [translatedTweet appendString:words[l]]; } 48
slide-49
SLIDE 49 // split the tweet into words NSMutableArray *words = [[tweet.body componentsSeparatedByString:@" "] mutableCopy]; // filter out the shorter words [words filterUsingPredicate:[NSPredicate predicateWithBlock: ^BOOL(id evaluatedObject, NSDictionary *bindings) { return [evaluatedObject length] > 7; }]]; // map each element of the words array to Børk for (int k = 0, kk = words.count; k < kk; k++) { words[k] = @"Børk"; } // reduce the words back into a new tweet NSString *translatedTweet = [words componentsJoinedByString:@" "]; 49
slide-50
SLIDE 50 let translation = split(tweet.body, { (char: Character) in char == " " }) .filter({ (word: String) in countElements(word) > 7 }) .map({ word in "Børk" }) .reduce("", combine: { $0 + " " + $1 }) 50
slide-51
SLIDE 51

Write

Less

Code

51
slide-52
SLIDE 52

Write&Less&Code

<"===">

52
slide-53
SLIDE 53

Write&Less&Code

<"===">

(less%is%more) 53
slide-54
SLIDE 54

FP#Checklist

Goal:&Reduce&Complexity

  • 1. Stop'branching'(use'closures)
  • 2. Stop'looping'(use'closures)
  • 3. Reduce'state'(use'immutability)
54
slide-55
SLIDE 55

Swi$'s'Dark'Underbelly

  • 1. It's'new,'and'somewhat'buggy
  • 2. Cumbersome'bridging
  • 3. No'more'dynamic'dispatch
  • 4. Duck@typing'is'no'longer'fun
  • 5. No'error@handling
55
slide-56
SLIDE 56

??

56
slide-57
SLIDE 57

Thank&You!

Please&evaluate&this&talk&with&the& GOTO&Mobile&App

Marc%Prud'hommeaux%/%marc@impathic.com but$you$can't$follow$me$on$Twi2er 57