think sharp, write swift
Post on 22-Jan-2017
128 Views
Preview:
TRANSCRIPT
THINK SHARP, WRITE SWIFTPASCAL BATTY
I’M A DEVELOPER
I’VE ALWAYS BEEN A MAC NERD
I SAW A LOT OF PEOPLE SWITCHING
I DON’T EVEN…
BASED ON SCIENTIFIC RESULTS
THE STAGES OF SWITCHING
😫 😯 😍
iOS
OS X
Apps
∞
Scripts + exe
OS X
Ubuntu
C# Swift
Object Oriented ✓ ✓
Type Inference ✓ ✓
Generics ✓ ✓
Tuples ✓ ✓
Lambdas ✓ ✓
Optional Chaining ✓ ✓
String Interpolation ✓ ✓
Operator overloading ✓ ✓
SWIFT VS C# FEATURE COMPARISON CHART
String Interpolation ✓ ✓
Operator overloading ✓ ✓
Null Coalescing ✓ ✓
Variadic Parameters ✓ ✓
Optional Parameters ✓ ✓
Extensions ✓ ✓
Auto-Properties ✓ ✓
Try/Catch ✓ ✓
Cool Logo ✓
THE GOOD OLD FIBONACCI SEQUENCE
LET’S COMPARE CODE
func fib(n: Int) -> Int { var fib0 = 0, fib1 = 1
for var i = 2; i <= n; i++ { var tmp = fib0 fib0 = fib1 fib1 = tmp + fib1 }
return n > 0 ? fib1 : 0 }
static int fib(int n) { int fib0 = 0, fib1 = 1;
for (int i = 2; i <= n; i++) { int tmp = fib0; fib0 = fib1; fib1 = tmp + fib1; }
return (n > 0 ? fib1 : 0); }
C# Swift
as found on Wikibooks
SWIFT AND C# ARE VERY SIMILAR
C# Swift
Garbage Collection Reference Counting
Interface Protocol
Constructor Initializer
const let
Linq MapReduce
Lambda Closure
func<> ->
SWIFT AND C# ARE KINDA SORTA SIMILAR
THE GOOD OLD FIBONACCI SEQUENCE
A FEW ADJUSTMENTS
func fib(n: Int) -> Int { var fib0 = 0, fib1 = 1
for var i = 2; i <= n; i++ { var tmp = fib0 fib0 = fib1 fib1 = tmp + fib1 }
return n > 0 ? fib1 : 0 }
Variable was never mutated; consider changing to ‘let’ constant
THE GOOD OLD FIBONACCI SEQUENCE
A FEW ADJUSTMENTS
func fib(n: Int) -> Int { var fib0 = 0, fib1 = 1
for var i = 2; i <= n; i++ { let tmp = fib0 fib0 = fib1 fib1 = tmp + fib1 }
return n > 0 ? fib1 : 0 }
++ is deprecated: it will be removed in Swift 3
THE GOOD OLD FIBONACCI SEQUENCE
A FEW ADJUSTMENTS
func fib(n: Int) -> Int { var fib0 = 0, fib1 = 1
for var i = 2; i <= n; i += 1 { let tmp = fib0 fib0 = fib1 fib1 = tmp + fib1 }
return n > 0 ? fib1 : 0 }
C-Style for statement is deprecated and will be removed…
THE GOOD OLD FIBONACCI SEQUENCE
A FEW ADJUSTMENTS
func fib(n: Int) -> Int { var fib0 = 0, fib1 = 1
for i in 2...n { let tmp = fib0 fib0 = fib1 fib1 = tmp + fib1 }
return n > 0 ? fib1 : 0 }
Immutable value ‘i’ was never used; consider replacing with ‘_’
THE GOOD OLD FIBONACCI SEQUENCE
A FEW ADJUSTMENTS
func fib(n: Int) -> Int { var fib0 = 0, fib1 = 1
for _ in 2...n { let tmp = fib0 fib0 = fib1 fib1 = tmp + fib1 }
return n > 0 ? fib1 : 0 }
😌
THE COMPILER IS PICKY BUT FRIENDLY
TYPE SYSTEM
LET US DIVE IN A LITTLE DEEPER
BUILDING BLOCKS
Class
Properties
Initializers
Instance Methods
Class Methods
Struct
Properties
Initializers
Instance methods
Static methods
Enum
Properties
Initializers
Instance methods
Static methods
VALUE TYPES ARE AWESOME
I CAN’T ASK YOU TO JUST BELIEVE ME ON THIS
VALUE TYPES ARE AWESOME
▸ Immutability ensured by ‘let’
▸ No expensive boxing/unboxing
▸ Code is more thread-safe
▸ Performance is better
▸ Functional Programming is more convenient
LET US DIVE IN A LITTLE DEEPER
STANDARD TYPES▸ Int, Float, Double
▸ Bool
▸ String, Character
▸ Array<T>, Dictionary<K: Hashable, V>, Set<T: Hashable>
THESE ARE ALL STRUCTS!
ENUMERABLES YOU WON’T BELIEVE WHAT HAPPENS NEXT…
BRACE YOURSELVES…
ENUMERABLES AS YOU MAY KNOW THEM
enum Land { case Forest case Mountain case Swamp case Plains case Island }
enum Error : Int { case NotFound = 404 case ServerError = 500 case Forbidden = 403 case Teapot = 418 }
Raw value can be String, Character or any numeric type
HERE COMES!
ENUMERABLES WITH ASSOCIATED VALUES!enum PaymentMethod { case Cash case Check (Int) case CreditCard (CardType, Int)
enum CardType { case Visa, MasterCard, Electron } func display() { switch self { case Cash: print("Paid by cash") case let Check(number): print("Paid by check #\(number)") case let CreditCard(type, number): print("Paid by \(type) #\(number)") } } }
let method = PaymentMethod.CreditCard(.Visa, 995423) method.display()
NOT OVER YET!
… AND GENERICS!enum Result<T, U> { case Success(T) case Error(U) }
enum Optional<T> { case Some(T) case None }
indirect enum Tree<T> { case Empty case Node(T, left: Tree<T>, right: Tree<T>) }
OPTIONALS (SPOILER: THEY’RE PRETTY COOL)
WHAT YOU MAY END UP DOING…
OPTIONALS IN THE WILD
let answer: String = "42" let numericAnswer = Int(answer)
let byOneThousand = numericAnswer * 1000
let nineThousand: Float = 9 * 1000
let vegetaSays: String = "It's over \(nineThousand) !!" let nappaSays: String = "What!? " + String(nineThousand) + "?!"
VALUE OF OPTIONAL TYPE ‘INT?’ NOT UNWRAPPED; DID YOU MEAN TO USE ‘!’ OR ‘?’ ?
Int?
BEAR WITH ME THERE
OPTIONALS
▸ Like nullables for all types!
▸ Variables, constants, arguments, properties or return values
▸ You can’t use its value unless you unwrap it first
▸ If it is not Optional, it can never be nil
FORGOT TO CHECK NULLABILITY?
WON’T LET YOU USE THE VALUE
DO YOU KNOW THE ‘MAYBE’ MONAD ?
UNWRAPPING THE OPTIONAL
42
let answer: String = getAnswer() let numericAnswer: Int? = Int(answer)
processNumericAnswer(numericAnswer)
???Int?
Int nil
DO YOU KNOW THE ‘MAYBE’ MONAD ?
UNWRAPPING THE OPTIONAL
42
let answer: String = getAnswer() let numericAnswer: Int? = Int(answer)
if let realAnswer: Int = numericAnswer { processNumericAnswer(realAnswer) } else { print("Please give a number") } nil
Int?Int?
NOT EVERYTHING IS COMPULSORY
OPTIONAL PROPERTIES
struct Contact { var firstName:String var middleName:String? var lastName:String var emailAddress:String var emailVerified:Bool }
THAT’S A LOT OF PUNCTUATION!
NULL COALESCING AND OPTIONAL CHAINING
let answer: String = getAnswer() let numericAnswer: Int? = Int(answer)
let sanitizedAnswer: Int = numericAnswer ?? 1 processNumericAnswer(sanitizedAnswer)
let contact: Contact? = getContact()
let email: String? = contact?.emailAddress
??
?.
FAMOUS LAST WORDS…
FORCE UNWRAP & IMPLICITLY UNWRAPPED OPTIONALS
!« I KNOW WHAT I’M DOING. IF YOU ENCOUNTER AN UNEXPECTED NIL JUST CRASH AT RUNTIME »
THERE’S MORE!
PUT SOME LOGIC INSIDE YOUR TYPES!
FUN WITH PROPERTIESstruct Contact { var firstName: String var middleName: String? var lastName: String
let securityNumber: Int var fullName: String { if let initial = middleName?.characters.first { return "\(firstName) \(initial). \(lastName)" } else { return "\(firstName) \(lastName)" } } var emailVerified: Bool var emailAddress: String { didSet { emailVerified = false } } }
MAP, FILTER, REDUCE, SORT
CLOSURESlet people:[Contact] = getContacts() let targetNames:[String] = people .filter({ contact in contact.lastName.hasPrefix("G") }) .map({ contact in contact.fullName }) .sort()
func multipleOf(factor: Int) -> Int -> Bool { return { (number: Int) in number % factor == 0 } }
let isEven = multipleOf(2) isEven(4)
// Get the sum of multiples of 3 up to 100
(1...100) .filter(multipleOf(3)) .reduce(0, combine: +)
https://github.com/mythz/swift-linq-examples
FUNCTIONAL PROGRAMMING
IMAGINE THE POSSIBILITIES…
EXTENSIONS & PROTOCOLSextension Contact { func composeEmailBoilerplate() -> String { … } var abbreviatedName: String { … } }
protocol StringSerializable { func serialize() -> String }
extension StringSerializable { func serialize() -> String { return "" }
}
extension Contact: StringSerializable { func serialize() -> String { … } }
PROTOCOL-ORIENTED PROGRAMMING
WHERE TO START
YOU’VE GOT TO START SOMEWHERE
YOUR LEARNING ENVIRONMENT
OS X Ubuntu Windows
XcodePlayground
REPL UbuntuBash
ONE OF THE PERKS OF DOING SWIFT ON THE MAC
PLAYGROUND
BECAUSE WE DON’T HAVE THE TIME TO SEE EVERYTHING
LEARN
▸ Updated eBook from Apple
▸ Available for free
▸ on iBooks
▸ on swift.org
▸ swiftdoc.org is a nice and fast documentation website
SOLVE PROBLEMS!
Exercism.io Codingame.com
😫
Picky Compiler
SyntaxError Handling
Optionals
IncompleteGenerics
ArgumentNaming
Noasync/await
Value Types
for loops
A POLARIZING ASPECT
ARGUMENT NAMING
(1...100) .filter(multipleOf(3)) .reduce(0, combine: +)
array.insert(0, 4)
array.insert(0, atIndex: 4)
😫
Picky Compiler
SyntaxError Handling
Optionals
IncompleteGenerics
ArgumentNaming
Noasync/await
Value Types
for loops
😯
Expressive code
guard.map().reduce()
Optionals
defer
AssociatedTypes Protocols
typedefEverything
enums
ClosuresValue Semantics
A CONVENTION-CREATING KEYWORD
GUARD
func multipleOf(factor: Int) -> Int -> Bool { return { (number: Int) in number % factor == 0 } }
A CONVENTION-CREATING KEYWORD
GUARD
func multipleOf(factor: Int) -> Int -> Bool { guard factor != 0 else { return { _ in false } } return { (number: Int) in number % factor == 0 } }
😯
Expressive code
guard.map().reduce()
Optionals
defer
AssociatedTypes Protocols
typedefEverything
enums
ClosuresValue Semantics
😍
Object-Oriented Programming
Functional Programming
Protocol-OrientedProgramming
THINK SHARP, WRITE SWIFT
THINK SWIFT
THANK YOU 💙Pascal Batty
@scalbattyscalbattyblog.soat.fr https://github.com/scalbatty/Think-Sharp-Write-Swift
top related