# [swift-evolution] [Proposal] Random Unification

Jonathan Hull jhull at gbis.com
Fri Dec 1 02:00:29 CST 2017

```> On Nov 30, 2017, at 11:11 PM, Martin Waitz <tali at admingilde.org> wrote:
>
> Hello,
>
>> The collection is a subject which has elements, and we are asking for one of them at random.
>
> it has elements, sure.
> And because of its structure, it has a first and a last element and whatever.
> But that random element is not an inherent property of the collection.
>
> I find it much more natural to use the random number generator to draw random elements from collections than the other way round.
> That approach also completely side-steps the problem with having to define default arguments. The user can just use any random number generator she has. Obviously, it makes sense to provide a default one named `random` to make it easily accessible.
>
>>>> var list = [1,2,3,4]
>>>> let a:Int? = list.randomElement //List is still [1,2,3,4] and ‘a’ contains one of the elements
>>>
>>> Instead I would prefer to have something like:
>>>
>>> let a = random.draw(from: list)
>>
>> But now the RNG has to understand the concept of collections. I would argue it is much cleaner to write an extension on Collection.
>>
>> func randomElement(using source: RandomSource = .default) -> Element? {
>> 	guard !isEmpty else {return nil}
>> 	let idx = Int.random(in: 0…(count - 1), using: source)
>> 	return self[idx]
>> }
>
> But then the Collection has to understand the concept of random numbers. ;-)
Not really.  Collection itself doesn’t have to change it’s structure at all.  We can just define a convenience function in an extension.

> Well both approaches are equally clean from this point of view:

With a protocol defining random() and random(in:), you could write generic algorithms on things which know how to create themselves from a RNG.  With your approach the RNG has to provide a way to get a random value for each type you want to support.

For example, without random(in:) or random(), how would you get a CGFloat between 0 and 1?  Ranges are only collections if they are countable…

>
> extension RandomFoo {
>    func draw<T: Collection>(from urn: T) -> T.Element? {
>        guard !urn.isEmpty else { return nil }
>        let idx = draw(from: urn.indices)
>        return urn[idx]
>    }
> }
>
This will call itself repeatedly and hang...

> We just have to define one base protocol for such extensions. Every random number generator then automatically knows how to draw elements from ranges and collections.

It isn’t automatic, thought.  How would I get a random color?

```