{"action":"created","issue":{"url":"https://api.github.com/repos/lorenzoracca/Swift-binary-search/issues/5","repository_url":"https://api.github.com/repos/lorenzoracca/Swift-binary-search","labels_url":"https://api.github.com/repos/lorenzoracca/Swift-binary-search/issues/5/labels{/name}","comments_url":"https://api.github.com/repos/lorenzoracca/Swift-binary-search/issues/5/comments","events_url":"https://api.github.com/repos/lorenzoracca/Swift-binary-search/issues/5/events","html_url":"https://github.com/lorenzoracca/Swift-binary-search/issues/5","id":142386755,"number":5,"title":"Binary vs unary predicates","user":{"login":"natecook1000","id":7053374,"avatar_url":"https://avatars.githubusercontent.com/u/7053374?v=3","gravatar_id":"","url":"https://api.github.com/users/natecook1000","html_url":"https://github.com/natecook1000","followers_url":"https://api.github.com/users/natecook1000/followers","following_url":"https://api.github.com/users/natecook1000/following{/other_user}","gists_url":"https://api.github.com/users/natecook1000/gists{/gist_id}","starred_url":"https://api.github.com/users/natecook1000/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/natecook1000/subscriptions","organizations_url":"https://api.github.com/users/natecook1000/orgs","repos_url":"https://api.github.com/users/natecook1000/repos","events_url":"https://api.github.com/users/natecook1000/events{/privacy}","received_events_url":"https://api.github.com/users/natecook1000/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":6,"created_at":"2016-03-21T15:39:12Z","updated_at":"2016-03-21T18:20:15Z","closed_at":null,"body":"With respect to Dave, I think focusing on unary predicates over binary ones is a mistake for a few different reasons:\r\n\r\n1. The standard library uses a consistent binary predicate for ordering collections. You can use the exact same binary predicate when calling `sort`, `partition`, `minElement`, and `maxElement`. Requiring a different predicate would make it harder to use these new APIs and inconsistent with what's there.\r\n\r\n2. Using a binary predicate makes the `Comparable` and predicate versions parallel. Like the existing methods described above, using a binary predicate would make these versions the same, allowing easy reversal of the direction of the sort and interoperation between methods.\r\n\r\n    ```swift\r\nvar a = [5, 3, 2, 6, 4, 1]\r\n// This is equivalent to 'a.sort(isOrderedBefore: <)':\r\na.sort()                               // [1, 2, 3, 4, 5, 6]\r\na.binarySearch(2)                      // Optional(1)\r\n\r\na.sort(isOrderedBefore: >)             // [6, 5, 4, 3, 2, 1]\r\na.binarySearch(2, isOrderedBefore: >)  // Optional(4)\r\n```\r\n\r\n3. Using a unary predicate requires flipping the semantics for `upperBound`. This is a problem, since `equalRange` can be implemented in terms of `lowerBound` and `upperBound` if the two methods use the same predicate, but not if one uses `isOrderedBefore` and one uses `isOrderedAfter`. The same problem is seen in the implementation of `binarySearch`: without a binary predicate, there's no way to test the equivalence of the lower bound.\r\n\r\nWhat do you think? In my view the most appropriate method signatures would be:\r\n\r\n```swift\r\n// where Generator.Element: Comparable\r\nfunc lowerBound(value: Generator.Element) -> Index\r\nfunc upperBound(value: Generator.Element) -> Index\r\nfunc equalRange(value: Generator.Element) -> Range<Index>\r\nfunc binarySearch(value: Generator.Element) -> Index?\r\n\r\n// general case\r\nfunc lowerBound(\r\n    value: Generator.Element,\r\n    isOrderedBefore isOrderedBefore: (Generator.Element, Generator.Element) -> Bool\r\n    ) -> Index\r\nfunc upperBound(\r\n    value: Generator.Element,\r\n    isOrderedBefore isOrderedBefore: (Generator.Element, Generator.Element) -> Bool\r\n    ) -> Index\r\nfunc equalRange(\r\n    value: Generator.Element,\r\n    isOrderedBefore isOrderedBefore: (Generator.Element, Generator.Element) -> Bool\r\n    ) -> Range<Index>\r\nfunc binarySearch(\r\n    value: Generator.Element,\r\n    isOrderedBefore isOrderedBefore: (Generator.Element, Generator.Element) -> Bool\r\n    ) -> Index?\r\n```"},"comment":{"url":"https://api.github.com/repos/lorenzoracca/Swift-binary-search/issues/comments/199411528","html_url":"https://github.com/lorenzoracca/Swift-binary-search/issues/5#issuecomment-199411528","issue_url":"https://api.github.com/repos/lorenzoracca/Swift-binary-search/issues/5","id":199411528,"user":{"login":"Haravikk","id":2184328,"avatar_url":"https://avatars.githubusercontent.com/u/2184328?v=3","gravatar_id":"","url":"https://api.github.com/users/Haravikk","html_url":"https://github.com/Haravikk","followers_url":"https://api.github.com/users/Haravikk/followers","following_url":"https://api.github.com/users/Haravikk/following{/other_user}","gists_url":"https://api.github.com/users/Haravikk/gists{/gist_id}","starred_url":"https://api.github.com/users/Haravikk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Haravikk/subscriptions","organizations_url":"https://api.github.com/users/Haravikk/orgs","repos_url":"https://api.github.com/users/Haravikk/repos","events_url":"https://api.github.com/users/Haravikk/events{/privacy}","received_events_url":"https://api.github.com/users/Haravikk/received_events","type":"User","site_admin":false},"created_at":"2016-03-21T18:20:14Z","updated_at":"2016-03-21T18:20:14Z","body":"While I'd love to be able to just pass the same predicate in, I don't like having to also pass a value to satisfy it.\r\n\r\nIs it possible that we could provide both forms? For example:\r\n\r\n    func lowerBound(isOrderedBefore:(T)->Bool) -> Index { … }\r\n    func lowerBound(value:T, predicate:(T,T)->Bool) -> Index {\r\n        return self.lowerBound(){ predicate($0, value) }\r\n    }\r\n\r\nThis could be a good middle-ground, as lets developers pass a predicate directly if they want to, alongside an element to compare against, otherwise for calling with a trailing closure the unary option is simpler."}}