Foward'|>'Pipe
h"p://github.com/jarsen/Pipes
Method'Chaining
[1,2,3,4,5].filter(isEven).map({$0 * 3}).reduce(0, combine: +) // 18
Method'Chaining
Array(1...5)
.filter(isEven)
.map({$0 * 3})
.reduce(0, combine: +) // 18
Func%on!Chaining
reduce(map(filter(1...5, isEven), {$0 * 3}), 0, +) // 18
"Hello" |> println
• Meet%the%Forward%Pipe%Operator%|>
• Popular%in%languages%such%as%F#%and%Elixir.
• Simply%applies%le>%hand%side%of%expression%as%first%argument%of%
funcAon%on%the%right
The$Forward$Pipe$Operator
2 |> increment // 3
5 |> (divide, 10) // 0.5
10 |> (divide, 5) // 2
Data$Pipelines
// the result of each step becomes first arg in the next
1...5
|> (filter, isEven) // [2, 4]
|> (map, {$0 * 3}) // [6, 12]
|> (reduce, 0, +) // 18
Data$Pipelines
students
// filter to students with last name L*
|> (filter, { $0.lastName.hasPrefix("L") }
// get list of all their first names
|> (map, Student.firstName)
// make all the names uppercase
|> (map, String.uppercaseString)
Op#onal<T>+Method+Chaining
let animalNoiseMap = ["cow":"moo", "dog":"woof", "cat":"meow"]
animalNoiseMap["dog"]?.uppercaseString // .Some("WOOF")
animalNoiseMap["fox"]?.uppercaseString // .None
Op#onal<T>+Func%on+Chaining
let animalNoiseMap = ["cow":"moo", "dog":"woof", "cat":"meow"]
map(animalNoiseMap["dog"]) { count(filter($0, isVowel)) } // .Some(2)
map(animalNoiseMap["fox"]) { count(filter($0, isVowel)) } // .None
Op#onal<T>+Pipeline
animalNoiseMap["dog"] // .Some("woof")
|> (filter, isVowel) // .Some(["o", "o"])
|> count // .Some(2)
Op#onal<T>+Pipeline
animalNoiseMap["fox"] // .None
|> (filter, isVowel) // .None
|> count // .None
Op#onal<T>+Pipeline
[2, 4, 6, 8, 10]
|> (map, increment) // [3, 5, 7, 9, 11]
|> (find, 7) // .Some(2)
|> isEven // .Some(true)
Op#onal<T>+Pipeline
[2, 4, 6, 8, 10]
|> (map, increment) // [3, 5, 7, 9, 11]
|> (find, 6) // .None
|> isEven // .None
Result<T>*Pipeline!
// uses https://github.com/antitypical/Result
func escapeInput(string: String) -> String { ... }
func readFile(fileName: String) -> Result<String> { ... }
func processText(string: String) -> String { ... }
let processedText = inputFileName
|> escapeInput
|> readFile
|> processText
Experimental,Forward,Pipes
|>> // apply as second argument
|>>> // apply as third argument
|< // apply as last argument
Benefits
• pipelines(are(about(composi'on,(encouraging(small,(pure,(
reusable(func3ons
• fewer("temporary"(variables(intended(for(use(on(next(line
• data(pipeline(reads(like(a(nice(list
• code(for(handling(values,(Optional<T>(and(Result<T>(is(the(
same:(avoid(if-lets(and(switches(and(without(knowledge(of(
monad(kung>fu
Non$Muta)ng+Helpers
Pure%versions%of%everything%in:
• ExtensibleCollectionType
• RangeReplaceableCollectionType
• MutableCollectionType
• Mutable)dic-onary)stuff
Currying
// curry the first argument at the end
func map<S: SequenceType, T>(f: S.Generator.Element->T)(seq: S) -> [T] {...}
1...5
|> filter(isEven) // [2, 4]
|> map({$0 * 3}) // [6, 12]
|> reduce(0, +) // 18
Non$Muta)ng+Helpers
Pipes&contains&curried&versions&of:
• map,#filter,#reduce
• ExtensibleCollectionType
• RangeReplaceableCollectionType
• MutableCollectionType
• Mutable#dic.onary#stuff
h"p://github.com/jarsen/Pipes
Feedback(/(Pull(Requests(much(appreciated
@jarsen(on(twi-er

Data Pipelines in Swift