import Foundation struct Person { var firstName: String var lastName: String var age: Int } extension Person { enum Query { case firstName(String) case lastName(String) case age(Int) func compare(person: Person) -> Bool { switch self { case .firstName(let firstName): return person.firstName == firstName case .lastName(let lastName): return person.lastName == lastName case .age(let age): return person.age == age } } } } class PhoneBook { let people = [Person(firstName: "Austin", lastName: "Feight")] func search(by options: [Person.Query]) -> Person? { let query = buildQuery(from: options) return people.filter(query).first } func buildQuery(from options: [Person.Query]) -> (Person) -> Bool { return { person in return options.map { $0.compare(person: person) } .reduce(true, &&) } } } PhoneBook().search(by: [.firstName("Austin"), .lastName("Feight")])