The Swift standard library begins with declarations of all the operators used throughout. All the familiar operators are there – arithmetic, logical, bitwise, bitshift, range, as well as the pattern matching and null coalescing operators. Later you find functions defined for each of these, so you can compare two Ints or append to an Array. But for one operator, there are no visible functions at all. To put it succinctly:

Swift’s internal header1 holds the answer—there are actually several functions defined for ~>, but only a few of them are accessible to us in a playground or compiled code. Now, the fact that these are available may be a fluke, and all indications are that these functions are solely meant for internal use. I wouldn’t advise anyone to use these in production code, since they could disappear or change at any time. With that said, in the spirit of exploration, let’s jump right in!

Visible declarations

func ~><T : _ForwardIndexType>(start: T, rest: (_Advance, T.Distance)) -> T
func ~><T : _ForwardIndexType>(start: T, rest: (_Advance, (T.Distance, T))) -> T
func ~><T : _BidirectionalIndexType>(start: T, rest: (_Advance, T.Distance)) -> T
func ~><T : _BidirectionalIndexType>(start: T, rest: (_Advance, (T.Distance, T))) -> T
func ~><T : _RandomAccessIndexType>(start: T, rest: (_Advance, (T.Distance))) -> T
func ~><T : _RandomAccessIndexType>(start: T, rest: (_Advance, (T.Distance, T))) -> T

func ~><T : _RandomAccessIndexType>(start: T, rest: (_Distance, (T))) -> T.Distance
func ~><T : _ForwardIndexType>(start: T, rest: (_Distance, T)) -> T.Distance

So what do we have there? Eight generic functions, each of which uses a *IndexType as the left-hand-side parameter. The eight functions really boil down to two (plus one variation): you can advance an index (with an optional limit) to get a new index, or you can get the distance from one index to another. But there’s a wrinkle—what goes on the right-hand side of this operator?

_Advance and _Distance

_Advance and _Distance are two structs that, while missing from the visible standard library, are usable from our code. The ~> declarations we’ve seen so far take a tuple on the right side, with one of these in the first spot of the tuple. Let’s try creating an _Advance tuple first:

let advanceBy5 = (_Advance(), 5)
> error: '_Advance' cannot be constructed because it has no accessible initializers
// darn.

So the compiler knows about the type, but we can’t construct it directly. Happily enough, the internal header also contains a few methods that return the tuples we’re looking for:

func _advance<D>(n: D) -> (_Advance, (D))
func _advance<D, I>(n: D, end: I) -> (_Advance, (D, I))

func _distanceTo<I>(end: I) -> (_Distance, (I))

Putting it to use

So what does this look like in practice? Let’s try a couple things:

// create an (_Advance, Int) tuple
let advanceBy5 = _advance(5)

// try it out on the members of an array
let shifted = [1, 2, 3, 4, 5].map { $0 ~> advanceBy5 }
println(shifted)
> [6, 7, 8, 9, 10]

// create a bound advance for a string and iterate through every other character
let line = "Beware the jabberwock, my son / the jaws that bite, the claws that catch"
let everyOther = _advance(2, line.endIndex)

var index = line.startIndex
while index != line.endIndex {
    print(line[index])
    index = index ~> everyOther
}
> Bwr h abrok ysn/tejw htbt,tecasta ac

Alright! I can’t totally tell why this would be preferred over the advance() and distance() functions, but perhaps there’s more there than I’m seeing. In any case, that’s how ~> can work, for at least these simplest of cases.

More under the hood

The other ~> function declarations have a similar structure, and therefore give similar clues about their purpose. The functions to generate these tuples, however, don’t bubble up to a level that we can access, so we’re locked out of these particular uses for ~>. Most of these have to do with collections, with an absolute value function thrown in for good measure.

func ~><T : _CollectionType>(x: T, _: (_CountElements, ())) -> T.Index.Distance
func ~><T>(x: EmptyCollection<T>, _: (_CountElements, ())) -> Int
func ~><T>(x: CollectionOfOne<T>, _: (_CountElements, ())) -> Int

func ~><T : _CollectionType>(x: T, _: (_UnderestimateCount, ())) -> Int
func ~><T : _SequenceType>(s: T, _: (_UnderestimateCount, ())) -> Int

func ~><T : _CollectionType, R>(s: T, args: (_PreprocessingPass, ((T) -> R))) -> R?
func ~><T : _SequenceType, R>(s: T, _: (_PreprocessingPass, ((T) -> R))) -> R?

func ~><S : _Sequence_Type>(source: S, _: (_CopyToNativeArrayBuffer, ())) -> _ContiguousArrayBuffer<S.Generator.Element>
func ~><C : CollectionType where C._Element == C._Element>(source: C, _: (_CopyToNativeArrayBuffer, ())) -> _ContiguousArrayBuffer<C._Element>

func ~><T : _SignedNumberType>(x: T, _: (_Abs, ())) -> T
func ~><T : AbsoluteValuable>(x: T, _: (_Abs, ())) -> T

That’s a wrap on our look at ~> - let me know if you have other ideas for how it could be used.

  1. I don’t know exactly what to call this—you can get the Swift REPL to dump the headers for an entire module with the :print_module command; it’s a variation on the result of command-clicking import Swift in a playground, with more declarations and less documentation.