Skip to content

Instantly share code, notes, and snippets.

@ijoshsmith
Last active April 8, 2017 12:51
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ijoshsmith/ee472ee30bb1f9bb17c6 to your computer and use it in GitHub Desktop.
Save ijoshsmith/ee472ee30bb1f9bb17c6 to your computer and use it in GitHub Desktop.
Higher-order functions in Swift
//
// main.swift
// HigherOrderFunctions
//
// Created by Joshua Smith on 12/6/15.
// Copyright © 2015 iJoshSmith. All rights reserved.
//
/*
This file contains simple implementations of several
higher-order functions in the Swift standard library.
These functions are not intended for production usage.
Always use the Swift standard library implementations.
*/
import Foundation
// Reduce
func _reduce<Element, Result>(
elements: [Element],
initial: Result,
combine: (accumulator: Result, element: Element) -> Result)
-> Result
{
var acc = initial
for elem in elements {
acc = combine(accumulator: acc, element: elem)
}
return acc
}
let sum = _reduce([1, 2, 3], initial: 0) { (acc, elem) in
acc + elem
}
print("sum = \(sum)") // prints: sum = 6
// Filter
func _filter<Element>(elements: [Element], include: Element -> Bool) -> [Element]
{
return _reduce(elements, initial: [Element]()) { (acc, elem) in
include(elem) ? acc + [elem] : acc
}
}
let evens = _filter([1, 2, 3]) { elem in
elem % 2 == 0
}
print("evens = \(evens)") // prints: evens = [2]
// Map
func _map<Element, Result>(elements: [Element], transform: Element -> Result) -> [Result]
{
return _reduce(elements, initial: [Result]()) { (acc, elem) in
acc + [transform(elem)]
}
}
let strings = _map([1, 2, 3]) { elem in String(elem) }
print("strings = \(strings)") // prints: strings = ["1", "2", "3"]
// Flat Map for optionals
func _flatMap<Element, Result>(elements: [Element], transform: Element -> Result?) -> [Result]
{
return _reduce(elements, initial: [Result]()) { (acc, elem) in
if let result = transform(elem) {
return acc + [result]
}
else {
return acc
}
}
}
let nonNils = _flatMap([1, nil, 3]) { $0 }
print("nonNils = \(nonNils)") // prints: nonNils = [1, 3]
// Flat Map for sequences
func _flatMap<SeqElement: SequenceType, Result: SequenceType>(
elements: [SeqElement], transform: [SeqElement.Generator.Element] -> Result)
-> [Result.Generator.Element]
{
let accumulator = Array<Result.Generator.Element>()
return _reduce(elements, initial: accumulator) { (acc, elem) in
return acc + transform(elem as! [SeqElement.Generator.Element])
}
}
let singleValues: [Int] = _flatMap([ [1], [2, 3], [], [4] ]) { array in
return array.count == 1 ? array : []
}
print("singleValues = \(singleValues)") // print: singleValues = [1, 4]
@ijoshsmith
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment