-- Copyright 1993-1998, by the Cecil Project -- Department of Computer Science and Engineering, University of Washington -- See the LICENSE file for license information. --DOC The `pair', `triple', and `quadruple' data structures can sometimes be --DOC useful, e.g., for returning a tuple of results from a function. ---------- -- Pairs ---------- --DOC A `pair' is an immutable pair of arbitrary values. A `pair' of two --DOC types `T1' and `T2' is a subtype of pairs of any supertypes `S1' and --DOC `S2', e.g., a `pair' of an `integer' and a `set' is a subtype of a --DOC `pair' of a `number' and an `unordered_collection'. The `pair' method --DOC constructs a new pair. (The constructor methods for pairs, triples, and --DOC quadruples do not start with `new_' -- like `cons', they are exceptions --DOC from our naming convention for constructor methods.) template object pair[T1,T2]; extend type pair[`T1,`T2] subtypes pair[`S1 >= T1, `S2 >= T2]; field first (@:pair[`T1,`T2]):T1; field second(@:pair[`T1,`T2]):T2; method pair(x:`T1, y:`T2):pair[T1,T2] { concrete object isa pair[T1,T2] { first := x, second := y } } method print_string(p@:pair[`T1,`T2]):string { "(" || p.first.print_string || ", " || p.second.print_string || ")" } extend pair[`T1 <= comparable[T1], `T2 <= comparable[T2]] isa comparable[pair[T1,T2]]; method =(p1@:pair[`T1 <= comparable[T1], `T2 <= comparable[T2]], p2@:pair[T1, T2]):bool { p1 == p2 | { p1.first = p2.first & { p1.second = p2.second } } } extend pair[`T1 <= partially_ordered[T1], `T2 <= partially_ordered[T2]] isa partially_ordered[pair[T1,T2]]; method <=(p1@:pair[`T1 <= partially_ordered[T1], `T2 <= partially_ordered[T2]], p2@:pair[T1, T2]):bool { p1.first <= p2.first & { p1.second <= p2.second } } method <(p1@:pair[`T1 <= partially_ordered[T1], `T2 <= partially_ordered[T2]], p2@:pair[T1, T2]):bool { p1 <= p2 & { not(p1 = p2) } } extend pair[`T1 <= hashable[T1], `T2 <= hashable[T2]] isa hashable[pair[T1,T2]]; method hash(p@:pair[`T1 <= hashable[T1], `T2 <= hashable[T2]], range:int):int { (p.first.hash(range) + p.second.hash(range) * 12093).hash(range) } ---------- -- Triples ---------- --DOC Triples are an immutable triple of arbitrary values. A `triple' of --DOC three types `T1', `T2', and `T3' is a subtype of triples of any --DOC supertypes `S1', `S2', and `S3'. The `triple' method --DOC constructs a new triple. template object triple[T1,T2,T3]; -- don't expose this inheritance to clients private extend triple[`T1,`T2,`T3] isa pair[T1,T2]; extend type triple[`T1,`T2,`T3] subtypes triple[`S1 >= T1, `S2 >= T2, `S3 >= T3]; field signature first (triple[`T1,`T2,`T3]):T1; field signature second(triple[`T1,`T2,`T3]):T2; field third(@:triple[`T1,`T2,`T3]):T3; method triple(x:`T1, y:`T2, z:`T3):triple[T1,T2,T3] { concrete object isa triple[T1,T2,T3] { first := x, second := y, third := z } } method print_string(p@:triple[`T1,`T2,`T3]):string { "(" || p.first.print_string || ", " || p.second.print_string || ", " || p.third.print_string || ")" } extend triple[`T1 <= comparable[T1], `T2 <= comparable[T2], `T3 <= comparable[T3]] isa comparable[triple[T1,T2,T3]]; method =(p1@:triple[`T1 <= comparable[T1], `T2 <= comparable[T2], `T3 <= comparable[T3]], p2@:triple[T1, T2, T3]):bool { p1 == p2 | { resend & { p1.third = p2.third } } } extend triple[`T1 <= partially_ordered[T1], `T2 <= partially_ordered[T2], `T3 <= partially_ordered[T3]] isa partially_ordered[triple[T1,T2,T3]]; method <=(p1@:triple[`T1 <= partially_ordered[T1], `T2 <= partially_ordered[T2], `T3 <= partially_ordered[T3]], p2@:triple[T1, T2, T3]):bool { resend & { p1.third <= p2.third } } extend triple[`T1 <= hashable[T1], `T2 <= hashable[T2], `T3 <= hashable[T3]] isa hashable[triple[T1,T2,T3]]; method hash(p@:triple[`T1 <= hashable[T1], `T2 <= hashable[T2], `T3 <= hashable[T3]], range:int):int { (resend + p.third.hash(range) * 2467).hash(range) } ---------- -- Quadruples ---------- --DOC Quadruples are also provided. template object quadruple[T1,T2,T3,T4]; -- don't expose this inheritance to clients private extend quadruple[`T1,`T2,`T3,`T4] isa triple[T1,T2,T3]; extend type quadruple[`T1,`T2,`T3,`T4] subtypes quadruple[`S1 >= T1, `S2 >= T2, `S3 >= T3, `S4 >= T4]; field signature first (quadruple[`T1,`T2,`T3,`T4]):T1; field signature second(quadruple[`T1,`T2,`T3,`T4]):T2; field signature third (quadruple[`T1,`T2,`T3,`T4]):T3; field fourth(@:quadruple[`T1,`T2,`T3,`T4]):T4; method quadruple(x:`T1, y:`T2, z:`T3, w:`T4):quadruple[T1,T2,T3,T4] { concrete object isa quadruple[T1,T2,T3,T4] { first := x, second := y, third := z, fourth := w } } method print_string(p@:quadruple[`T1,`T2,`T3,`T4]):string { "(" || p.first.print_string || ", " || p.second.print_string || ", " || p.third.print_string || ", " || p.fourth.print_string || ")" } extend quadruple[`T1 <= comparable[T1], `T2 <= comparable[T2], `T3 <= comparable[T3], `T4 <= comparable[T4]] isa comparable[quadruple[T1,T2,T3,T4]]; method =(p1@:quadruple[`T1 <= comparable[T1], `T2 <= comparable[T2], `T3 <= comparable[T3], `T4 <= comparable[T4]], p2@:quadruple[T1, T2, T3, T4]):bool { p1 == p2 | { resend & { p1.fourth = p2.fourth } } } extend quadruple[`T1 <= partially_ordered[T1], `T2 <= partially_ordered[T2], `T3 <= partially_ordered[T3], `T4 <= partially_ordered[T4]] isa partially_ordered[quadruple[T1,T2,T3,T4]]; method <=(p1@:quadruple[`T1 <= partially_ordered[T1], `T2 <= partially_ordered[T2], `T3 <= partially_ordered[T3], `T4 <= partially_ordered[T4]], p2@:quadruple[T1, T2, T3, T4]):bool { resend & { p1.fourth <= p2.fourth } } extend quadruple[`T1 <= hashable[T1], `T2 <= hashable[T2], `T3 <= hashable[T3], `T4 <= hashable[T4]] isa hashable[quadruple[T1,T2,T3,T4]]; method hash(p@:quadruple[`T1 <= hashable[T1], `T2 <= hashable[T2], `T3 <= hashable[T3], `T4 <= hashable[T4]], range:int):int { (resend + p.fourth.hash(range) * 2467).hash(range) }