Skip to content

Instantly share code, notes, and snippets.

@brentsimmons
Created August 5, 2015 18:07
Show Gist options
  • Save brentsimmons/7ec7e3669ff7ad17e446 to your computer and use it in GitHub Desktop.
Save brentsimmons/7ec7e3669ff7ad17e446 to your computer and use it in GitHub Desktop.
//: Playground - noun: a place where people can play
import Cocoa
protocol Account: Equatable {
var accountID: String {get}
}
// https://twitter.com/optshiftk/status/628985834801336320
func ==<T: Account>(lhs: T, rhs: T) -> Bool {
return lhs.accountID == rhs.accountID
}
class FooAccount: Account {
let accountID = "foo"
}
class BarAccount: Account {
let accountID = "bar"
}
let foo = FooAccount()
let bar = BarAccount()
var accounts = [Account]()
// Error on line 29: protocol 'Account' can only be used as a generic constraint because it has Self or associated type requirements
@jazzbox
Copy link

jazzbox commented Dec 16, 2015

import Cocoa

protocol AnyEquatable {

    func isEqual(other: Any) -> Bool
}

protocol Account: AnyEquatable {

    var accountID: String {get}

}

extension SequenceType where Generator.Element : AnyEquatable {

    func containsAny(element: Any) -> Bool {
        for e in self {
            if e.isEqual(element) {
                return true
            }
        }
        return false
    }
}

func containsAccount(accounts: [Account], element: Account) -> Bool {
    for e in accounts {
        if e.isEqual(element) {
            return true
        }
    }
    return false
}


func containsT<T: AnyEquatable>(array: [T], element: T) -> Bool {
    for e in array {
        if e.isEqual(element) {
            return true
        }
    }
    return false
}


class FooAccount: Account {

    let accountID = "foo"

    func isEqual(other: Any) -> Bool {
        guard let _ = other as? FooAccount else {
            return false
        }
        return true // TODO
    }

}

class BarAccount: Account {

    let accountID = "bar"

    func isEqual(other: Any) -> Bool {
        guard let _ = other as? BarAccount else {
            return false
        }
        return true // TODO
    }

}

let foo = FooAccount()
let bar = BarAccount()

var accounts: [Account] = [foo, bar]

containsAccount(accounts, element: foo) // works

containsT(accounts, element: foo) // error: Cannot convert value of type '[Account]' to expected argument type '[_]'

accounts.containsAny(foo) // error: Using 'Account' as a concrete type conformint to protocol 'AnyEquatable' is not supported

@freedom27
Copy link

protocol Account {
    var accountID: String { get }
}

extension SequenceType where Self.Generator.Element == Account {
    func contains(element: Self.Generator.Element) -> Bool {
        for currentElement in self {
            if currentElement.accountID == element.accountID {
                return true
            }
        }
        return false
    }
}

class FooAccount: Account {
    let accountID = "foo"
}

class BarAccount: Account {
    let accountID = "bar"
}

let foo = FooAccount()
let bar = BarAccount()
var accounts = [Account]()

if !accounts.contains(foo) { // works
    accounts.append(foo)
}

if !accounts.contains(bar) { // works
    accounts.append(bar)
}

@wildthink
Copy link

How about this?

import Cocoa

protocol Feed {
    var url: String {get}
    func isEqualTo(other: Feed) -> Bool
}

extension Feed where Self: Equatable {
    func isEqualTo(other: Feed) -> Bool {
        return url == other.url
    }
}

func ==<T: Feed where T:Equatable> (lhs: T, rhs: T) -> Bool {
    return lhs.isEqualTo(rhs)
}

protocol Folder {
    var feeds: [Feed] {get}
    func addFeeds(feedsToAdd: [Feed])
}

// This could be done if the Folder feeds had a { get set }
//extension Folder {
//    func addFeeds(feedsToAdd: [Feed]) {
//        for oneFeed in feedsToAdd {
//            if !feeds.contains({ $0.isEqualTo (oneFeed) }) {
//                feeds += [oneFeed]
//            }
//        }
//    }
//}

class LocalFeed: Feed {
    var url: String
    init(url: String) {
        self.url = url
    }
}
extension LocalFeed: Equatable {}

class LocalFolder: Folder {

    var feeds = [Feed]()

    func addFeeds(feedsToAdd: [Feed]) {
        for oneFeed in feedsToAdd {
            if !feeds.contains({ $0.isEqualTo (oneFeed) }) {
                feeds += [oneFeed]
            }
        }
    }
}

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