"Given a stream of tuples, return two streams. The first stream produces the first elements of the given tuples, and the second stream produces the remaining elements of the given tuples. Thus: tuples[i] == [unzip(tuples)[0][i], *unzip(tuples)[1][i]]" tagged("Streams") shared [Iterable<Head,Absent>, Iterable<Tail,Absent>] unzip<Element,Head,Tail,Absent> (Iterable<Tuple<Element|Head,Head,Tail>,Absent> tuples) given Tail satisfies Element[] given Absent satisfies Null => [tuples.map((Tuple<Element|Head,Head,Tail> tuple) => tuple.first), tuples.map((Tuple<Element|Head,Head,Tail> tuple) => tuple.rest)]; "Given a stream of pairs, return two streams. The first stream produces the first elements of the given pairs, and the second stream produces the second elements of the given pairs. Thus: pairs[i] == [unzipPairs(pairs)[0][i], unzipPairs(pairs)[1][i]]" tagged("Streams") shared [Iterable<First,Absent>, Iterable<Second,Absent>] unzipPairs<First,Second,Absent> (Iterable<[First,Second],Absent> pairs) given Absent satisfies Null => [pairs.map(([First,Second] pair) => pair[0]), pairs.map(([First,Second] pair) => pair[1])]; "Given a stream of entries, return two streams. The first stream produces the keys of the given entries, and the second stream produces the items of the given entries. Thus: entries[i] == unzipEntries(entries)[0][i] -> unzipEntries(entries)[1][i]" tagged("Streams") shared [Iterable<Key,Absent>, Iterable<Item,Absent>] unzipEntries<Key,Item,Absent> (Iterable<<Key->Item>,Absent> entries) given Key satisfies Object given Absent satisfies Null => [entries.map(Entry<Key,Item>.key), entries.map(Entry<Key,Item>.item)];