Writing these kinds of wrappers is a pretty standard trick when dealing with some of Swift’s shortcomings around protocols. You can see it in the standard library with AnySequence
and AnyHashable
, and you may have encountered an AnyError
type that wraps any error for contexts that require a type that conforms to Error
, but you have an Error
value itself, which, before Swift 5, didn’t conform to Error
and needed to be wrapped.
This is a standard trick, but it’s interesting in our context. Swift provided a very local solution to solving randomness: when you call Int.random(in:using:)
, you have a very specific input that can control the randomness. Swift gave no solution or guidance for controlling randomness globally across an entire application. If you sprinkle various random
functions throughout your application, you need to control each one individually.
It turns out that the Environment
struct is the perfect to control Swift’s APIs globally. Even if you didn’t want to use Gen
, you could use Environment
to control Swift’s APIs to be testable.
We could probably do something even nicer if we used Gen
, but for the moment it’s still completely uncontrollable. Maybe we can take control of Gen
in a way similar to how we took control of Swift’s APIs.