# OptionSetType & Integers & Generics

My son wanted to exercise math on the iPad. He likes math, which is good.
We tried several apps, but nothing suits his needs. I did end up
in the Xcode.

Started with implementation of `MathOperation`. `OptionSetType` looked like
a good choice. He can exercise one operation, any combination or all of them.
Here’s the `OptionSetType` documentation.

Later on, I came to the point where I wanted to select random `MathOperation` from
provided options. But how? There’s no easy way and it seems that `enum` & `Set`
would be much better. But let it be and finish it with `OptionSetType`. Just to

• Conversion of `OptionSetType` to an array of single options. In other
words – we need to convert `OptionSetType` to `Array<OptionSetType>`.
• Generic implementation – any integer type can be used as `RawValue` (`OptionSetType`).

## Integers

All integer types (`Int`, …) are structs in Swift. All of them conform to slightly
different set of protocols. Here’s the quick overview:

Lot of protocols omitted to make it more readable. Common ancestor for all integer
types is `IntegerType` protocol. Great, I’m going to stick with it. Let’s
define `OptionSetType` extension in this way:

Next step is to iterate over all single bit values (power of two), check if they’re set
and add them to an array. I do like generators, so, let’s introduce `BitValuesGenerator`
and implement `array` property with it.

## BitValuesGenerator

What do I want? In case of:

• `UInt8` – 1, 2, 4, 8, 16, 32, 64, 128
• `Int8` – 1, 2, 4, 8, 16, 32, 64

Signed integer
does use one bit for sign (minus, plus) and I’m going to ignore this bit.

### Left shift

One can think that I can use `<<` operator.

No, I can’t. This code doesn’t compile. Operator `<<` cannot be applied to
operands of type `Element` and `Int`. And it cannot be applied to two
`Element` operands as well even when `Element` is `IntegerType`.
The problem lies in the Swift standard library.

Copy & paste for all integer types, but there’s no `<<` operator for `IntegerType`.

### Optional left shift

What now? Going introduce new `<<?` operator – left shift or `nil` if overflow happens.
And for `IntegerType` instead of copy & pasting it for all integer types.

Now I’m going to check Swift standard library to see what can I do with
`IntegerType`.

`toIntMax()`? No way. `Int64` maximum value is `2^63 - 1`. `UInt64` maximum value is `2^63`.
`toIntMax()` converts integer to `IntMax` (typealias for `Int64`). And `Int64` can’t hold `2^63` =
overflow = crash in case where `RawValue` of `OptionSetType` is `UInt64` and `2^63` is used
as `rawValue`.

`multiplyWithOverflow`? Left shift is multiplication by 2. Result type of this function
is `(Self, overflow: Bool)`. Where `Self` is multiplication result and `overflow` indicates
if overflow happened or not. Useful.

Safe left shift for `IntegerType` done and I can fix broken `BitValuesGenerator`.

## Random generator

Finally I can extend `OptionSetType` with `randomGenerator()` as well.

We have working generic random option generator for `IntegerType`.

## Conclusion

Go back to the Swift standard library and check `IntegerType` documentation
again.

Useful functions are hidden in protocols with prefix `_`. And these protocols
documentation says: This protocol is an implementation detail of …; do
not use it directly
. Bummer.

Another approach can be `&*`.

Updated `<<?` implementation.

Probably safer way in terms of `_` protocols & implementation details. On the other side,
all these functions are available (again copy & paste) on all integer types as well.

Maybe it’s okay to use `_IntegerArithmeticType.multiplyWithOverflow`. Don’t know, not
100% sure and don’t have good feeling about it when working with `IntegerType`.

Anyway, you can find both implementations in
this gist.
Choose whatever feels safer to you.

What I would like to see in Swift 3? Better generics support for integer types

• more operators in standard library. I would like to work with `IntegerType` as
with any other integer type like `Int8`, … Type safety is good, really
good, but it makes things harder to do sometimes.