+(define (peers-union . peer-sets)
+ (define groups
+ (foldl
+ (λ (p groups)
+ (hash-update groups (Peer-uri-str p) (λ (group) (cons p group)) '()))
+ (hash)
+ (append* (map set->list peer-sets))))
+ (define (merge peers)
+ (match peers
+ ['() (raise 'impossible)]
+ [(list p) p]
+ [(list* p1 p2 ps)
+ (let* ([n1 (Peer-nick p1)]
+ [n2 (Peer-nick p2)]
+ [p (cond
+ [(and (not n1) (not n2)) p1]
+ [(and n1 n2 ) p1]
+ [(and n1 (not n2)) p1]
+ [(and (not n1) n2) p2]
+ [else
+ (raise 'impossible)])])
+ (merge (cons p ps)))]))
+ (make-immutable-peers (map merge (hash-values groups))))
+
+(module+ test
+ (let* ([u1 "http://foo/bar"]
+ [u2 "http://baz/quux"]
+ [p1 (Peer #f (string->url u1) u1 #f)]
+ [p2 (Peer "a" (string->url u1) u1 #f)]
+ [p3 (Peer "b" (string->url u2) u2 #f)]
+ [s1 (make-immutable-peers (list p1))]
+ [s2 (make-immutable-peers (list p2 p3))])
+ (check-true (peers? (peers-union s1 s2)))
+ (check-true (peers? (peers-union s2 s1)))
+ (check-equal? (list p3 p2) (set->list (peers-union s1 s2)))
+ (check-equal? (list p3 p2) (set->list (peers-union s2 s1)))))
+