You could also cache the Set values into a pre-allocated Array for faster indexed lookup. That way you only need the slower index into Set once.

Here’s an example to show what I mean:

Method 1: No caching - direct indexing into Set:

```
function Base.getindex(S::IntSet, i::Integer)
if 1 <= i <= length(S)
state = start(S)
x = 0
for j = 1:i
x, state = next(S, state)
end
return x
else
throw(BoundsError(S, i))
end
end
function pairstuff1(S::AbstractSet, isprint=false)
for i = 1:length(S), j = (i+1):length(S)
x1 = S[i]
x2 = S[j]
end
end
```

Method 2: Caching - index into Set once only, then index into pre-allocated Array

```
const A = Vector{Int}(64);
function pairstuff2(S::AbstractSet, isprint=false)
# populate array
i = 0
for x in S
i += 1
A[i] = x
end
# pairwise stuff
for i = 1:length(S), j = (i+1):length(S)
x1 = A[i]
x2 = A[j]
end
end
```

Now some benchmarking …

```
using BenchmarkTools
S = IntSet([5, 10, 15, 55])
@benchmark pairstuff1($S)
@benchmark pairstuff2($S)
```

On my machine, cached version is about 5 times faster.