Seán Labastille

Logo

View My GitHub Profile

3 February 2016

struct Set { var first { get } }

by

Welcome to Swift: Shuffle All.

While some of us may have fond memories of these friendly words greeting users in iOS 7’s Music app, these days we must turn elsewhere to appreciate a random ordering of collections.

Swift: Shuffle All is intended as one option to satisfy this need by bringing together Nate Cook’s SwiftDoc.org and a source of random indexes (RandomAccessIndexType anyone?) as a means to explore Swift’s standard library and built-ins in a more serendipitous fashion.

Rather than hoping for a conference talk to mention that API you always wanted to know about:

entropy may well do a better job of surfacing it before you need it.

While so far no well-defined method exists for choosing subject matter from SwiftDoc.org, Chris kindly provided inspiration for this initial exploration:

Investigating the protocol hierarchy for Set, or rather: Set<Element : Hashable> is revealing. Conforming to CollectionType places several requirements on Set, in particular providing a Generator for interation and Index for representing collection indices.

CollectionType thus also requires that a Set provides an instance variable defined as:

So far, so good. However this doesn’t tell us how first element is determined when iterating.

On the other hand, we now have a place to go and find these details: the Swift source at https://github.com/apple/swift An initial search for struct Set doesn’t yield any results in Swift source files, however a HashedCollections.swift.gyb file looks promising.

Further investigation reveals these are parsed by a tool included in the repository dubbed Generate Your Boilerplate. Clearly some tooling work has been done to ease Swift development.

Back to HashedCollections.swift.gyb. Running this through

utils/gyb stdlib/public/core/HashedCollections.swift.gyb > HashedCollections.swift

inflates a somewhat larger Swift source file.

This seems to contain two rather similar clusters of types, one for Dictionaries and another for Sets. In fact, much of this was investigated in Ankit Aggarwal’s Exploring Swift Dictionary Implementation(Although they don’t seem to have shown their hand about where this information was gleaned from.)

Both Dictionary and Set share their HashedContainerStorageHeader while a Set consists only of keys as opposed to a Dictionary which must store keys and values.

Since buckets for keys are looked up by their hashValue, this suggests a Set’s first object will depend on its hashValue. Well, almost. As the hashValue is squeezed to fit the header bitmap which is sized based on the Set’s capacity, a sufficiently large capacity for the range of hashValues must be choosen to allow this sorting to take place.

Have a look at this Playground page to experiment with this behaviour. Simply drag the page into an existing playground to get started.

tags: