[Proposal] Random Unification

IMO, we should have a `Random` or `RandomGenerator` interface and the stdlib can provide a `SystemRandom` that wraps arc4*/random(), and maybe a cryptographically secure one too (MT19937?).

protocol RandomGenerator {
    func uniform() -> Int
    func uniform() -> Double
    func uniformBytes(count: Int) -> Data
}

Then we could add things like, e.g. a protocol extension to generate normally distributed numbers (https://en.wikipedia.org/wiki/Box–Muller_transform).

extension RandomGenerator {
    func normal<T: FloatingPoint>() -> (T, T) {
        // ...
    }
}

···

On Sep 8, 2017, at 10:08 AM, Shawn Erickson via swift-evolution <swift-evolution@swift.org> wrote:

It would be nice to leverage range support instead of a start and end value IMHO.
On Fri, Sep 8, 2017 at 9:52 AM Alejandro Alonso via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Hello swift evolution, I would like to propose a unified approach to `random()` in Swift. I have a simple implementation here https://gist.github.com/Azoy/5d294148c8b97d20b96ee64f434bb4f5. This implementation is a simple wrapper over existing random functions so existing code bases will not be affected. Also, this approach introduces a new random feature for Linux users that give them access to upper bounds, as well as a lower bound for both Glibc and Darwin users. This change would be implemented within Foundation.

I believe this simple change could have a very positive impact on new developers learning Swift and experienced developers being able to write single random declarations.

I’d like to hear about your ideas on this proposal, or any implementation changes if need be.

- Alejando

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Quick thoughts:

1. A stdlib-level random number facility should default to a host-provided CSPRNG as the generator. Anything less is really not justifiable. The throughput of modern HW-backed CSPRNGs exceeds that of all but the fastest PRNGs, anyway.

2. MT is not a CSPRNG.

– Steve

···

On Sep 8, 2017, at 1:31 PM, Kevin Nattinger via swift-evolution <swift-evolution@swift.org> wrote:

IMO, we should have a `Random` or `RandomGenerator` interface and the stdlib can provide a `SystemRandom` that wraps arc4*/random(), and maybe a cryptographically secure one too (MT19937?).

protocol RandomGenerator {
    func uniform() -> Int
    func uniform() -> Double
    func uniformBytes(count: Int) -> Data
}

Then we could add things like, e.g. a protocol extension to generate normally distributed numbers (https://en.wikipedia.org/wiki/Box–Muller_transform).

extension RandomGenerator {
    func normal<T: FloatingPoint>() -> (T, T) {
        // ...
    }
}

On Sep 8, 2017, at 10:08 AM, Shawn Erickson via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

It would be nice to leverage range support instead of a start and end value IMHO.
On Fri, Sep 8, 2017 at 9:52 AM Alejandro Alonso via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Hello swift evolution, I would like to propose a unified approach to `random()` in Swift. I have a simple implementation here https://gist.github.com/Azoy/5d294148c8b97d20b96ee64f434bb4f5. This implementation is a simple wrapper over existing random functions so existing code bases will not be affected. Also, this approach introduces a new random feature for Linux users that give them access to upper bounds, as well as a lower bound for both Glibc and Darwin users. This change would be implemented within Foundation.

I believe this simple change could have a very positive impact on new developers learning Swift and experienced developers being able to write single random declarations.

I’d like to hear about your ideas on this proposal, or any implementation changes if need be.

- Alejando

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Range support is something that came up, and I think it’s a great idea as well. My question now is do we support both `CountableRange` and `CountableClosedRange`?

···

On Sep 8, 2017, 12:08 PM -0500, Shawn Erickson <shawnce@gmail.com>, wrote:
It would be nice to leverage range support instead of a start and end value IMHO.
On Fri, Sep 8, 2017 at 9:52 AM Alejandro Alonso via swift-evolution <swift-evolution@swift.org<mailto:swift-evolution@swift.org>> wrote:
Hello swift evolution, I would like to propose a unified approach to `random()` in Swift. I have a simple implementation here https://gist.github.com/Azoy/5d294148c8b97d20b96ee64f434bb4f5. This implementation is a simple wrapper over existing random functions so existing code bases will not be affected. Also, this approach introduces a new random feature for Linux users that give them access to upper bounds, as well as a lower bound for both Glibc and Darwin users. This change would be implemented within Foundation.

I believe this simple change could have a very positive impact on new developers learning Swift and experienced developers being able to write single random declarations.

I’d like to hear about your ideas on this proposal, or any implementation changes if need be.

- Alejando

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org<mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

Let me be precise: it is absolutely possible to outperform CSPRNGs. They have simply become fast enough that the performance gap doesn’t matter for most uses (let’s say amortized ten cycles per byte or less—whatever you are going to do with the random bitstream will be much more expensive than getting the bits was).

That said, yes, there should definitely be other options. It should be possible for users to get reproducible results from a stdlib random interface run-to-run, and also across platforms. That alone requires that at least one other option for a generator be present. There may also be a place for a very high-throughput generator like xorshiro128+.

All I’m really saying is that the *default* generator should be an os-provided unseeded CSPRNG, and we should be very careful about documenting any generator options.

– Steve

···

On Sep 8, 2017, at 8:09 PM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

This topic has been broached on Swift Evolution previously. It's interesting to me that Steve Canon is so certain that CSPRNGs are the way to go. I wasn't aware that hardware CSPRNGs have come such a long way and are so ubiquitous as to be feasible as a basis for Swift random numbers. If so, great.

Otherwise, if there is any way that a software, non-cryptographically secure PRNG is going to outperform a CSPRNG, then I think it's worthwhile to have a (carefully documented) choice between the two. I would imagine that for many uses, such as an animation in which you need a plausible source of noise to render a flame, whether that is cryptographically secure or not is absolutely irrelevant but performance may be key.

When Apple added GameplayKit to iOS, they added randomisation functions.
Could that implementation be repeated in Swift Foundation?

···

On Mon, Sep 11, 2017 at 2:48 AM, Susan Cheng via swift-evolution < swift-evolution@swift.org> wrote:

Hello,

I have an implementation for reference
https://github.com/SusanDoggie/Doggie/blob/master/Sources/Doggie/
Foundation/Random.swift

It's easy to remind that what's the range of random floating point number

Double.random(includeOne: true)
Double.random(includeOne: false)

2017-09-09 0:52 GMT+08:00 Alejandro Alonso via swift-evolution
<swift-evolution@swift.org>:
> Hello swift evolution, I would like to propose a unified approach to
> `random()` in Swift. I have a simple implementation here
> https://gist.github.com/Azoy/5d294148c8b97d20b96ee64f434bb4f5. This
> implementation is a simple wrapper over existing random functions so
> existing code bases will not be affected. Also, this approach introduces
a
> new random feature for Linux users that give them access to upper
bounds, as
> well as a lower bound for both Glibc and Darwin users. This change would
be
> implemented within Foundation.
>
> I believe this simple change could have a very positive impact on new
> developers learning Swift and experienced developers being able to write
> single random declarations.
>
> I’d like to hear about your ideas on this proposal, or any implementation
> changes if need be.
>
> - Alejando
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

- I’d love to see several of the most common random kinds supported, and I agree it would be nice (but not required IMO) for the default to be cryptographically secure.

I would be very careful about choosing a "simple" solution. There is a log, sad history of languages trying to provide a "simple" random number generator and accidentally providing a powerful footgun instead. But:

- We should avoid the temptation to nuke this mosquito with a heavy handed solution designed to solve all of the world’s problems: For example, the C++ random number stuff is crazily over-general. The stdlib should aim to solve (e.g.) the top 3 most common cases, and let a more specialized external library solve the fully general problem (e.g. seed management, every distribution imaginable, etc).

That's not to say we need to have seven engines and twenty distributions like C++ does. The standard library is not a statistics package; it exists to provide basic abstractions and fundamental functionality. I don't think it should worry itself with distributions at all. I think it needs to provide:

  1. The abstraction used to plug in different random number generators (i.e. an RNG protocol of some kind).

  2. APIs on existing standard library types which perform basic randomness-related functions correctly—essentially, encapsulating Knuth. (Specifically, I think selecting a random element from a collection (which also covers generating a random integer in a range), shuffling a mutable collection, and generating a random float will do the trick.)

  3. A default RNG with a conservative design that will sometimes be too slow, but will never be insufficiently random.

If you want to pick elements with a Poisson distribution, go get a statistics framework; if you want repeatable random numbers for testing, use a seedable PRNG from XCTest or some other test tools package. These can leverage the standard library's RNG protocol to work with existing random number generators or random number consumers.

···

On Sep 9, 2017, at 10:31 PM, Chris Lattner via swift-evolution <swift-evolution@swift.org> wrote:

--
Brent Royal-Gordon
Architechies

I completely agree with you on all points, but I was wondering about the numeric types getting random initializers. I think it’s a great idea, but is this something that should be discussed in a separate proposal? My current goals for the proposal is creating the actual random API, then discussing ideas for additions to RandomAccessCollection+MutableCollection to include .random and .shuffle like Ben mentioned, along with the addition of the numeric initializers.

- Alejandro

···

On Sep 10, 2017, 12:31 AM -0500, Chris Lattner <clattner@nondot.org>, wrote:

On Sep 8, 2017, at 9:52 AM, Alejandro Alonso via swift-evolution <swift-evolution@swift.org<mailto:swift-evolution@swift.org>> wrote:

Hello swift evolution, I would like to propose a unified approach to `random()` in Swift. I have a simple implementation here https://gist.github.com/Azoy/5d294148c8b97d20b96ee64f434bb4f5. This implementation is a simple wrapper over existing random functions so existing code bases will not be affected. Also, this approach introduces a new random feature for Linux users that give them access to upper bounds, as well as a lower bound for both Glibc and Darwin users. This change would be implemented within Foundation.

I believe this simple change could have a very positive impact on new developers learning Swift and experienced developers being able to write single random declarations.

I’d like to hear about your ideas on this proposal, or any implementation changes if need be.

My 2c:

- I’d love to see some random number initializers get added as initializers on the numeric types. This is a long standing hole and it would be hugely valuable to fill it.
- I’d love to see several of the most common random kinds supported, and I agree it would be nice (but not required IMO) for the default to be cryptographically secure.
- We should avoid the temptation to nuke this mosquito with a heavy handed solution designed to solve all of the world’s problems: For example, the C++ random number stuff is crazily over-general. The stdlib should aim to solve (e.g.) the top 3 most common cases, and let a more specialized external library solve the fully general problem (e.g. seed management, every distribution imaginable, etc).

In terms of approach, I’d suggest looking at other libraries that are conceptually similar, e.g. the “simple random data” APIs for numpy:
https://docs.scipy.org/doc/numpy-1.13.0/reference/routines.random.html

Things like “return a random number from 0 to 1.0, 0 to N, 0 to INTMAX, sample from a normal/gaussian distribution, and maybe one more should be enough.

-Chris

I'm okay with "unqualified" random being crypto-secure and qualifying non-crypto-secure generators as inferior, but I think that Unsafe is not the qualifier we are looking for. Everywhere else, Unsafe implies that misuse will cause unpredictable results/crashes, which is a different class of problems than the one that this tries to avoid. Maybe InsecureRandom? Pseudorandom? PredictableRandom?

The subtype relationships seem problematic to me: any UnsafeRandomSource is probably also a RandomSource. This means that you can't design an API requiring a RandomSource and assume that you'll get a crypto-secure one. Granted, anyone can pretend that their random is crypto-secure while it isn't, but I feel like this should be an important API hint.

I'm not convinced that `RandomSource` needs a `shared` property. By definition, you shouldn't be able to tell which RandomSource instance generated some random number, so it doesn't matter if you have multiple instances of it, or just one. It could be a flyweight and we'd be none the wiser. Requiring a shared instance also forces the implementation to be thread-safe, which is almost certainly not a desirable feature for an API meant to have a huge throughput.

To me, the tradeoff between "secure" and "insecure" seems to be that "secure" RNGs have an unpredictable result (which is suitable for crypto operations), and "insecure" RNGs can be seeded and repeated, which is a desirable feature in many scenarios. Then, there are some low-stake cases where that probably doesn't really matter (like in a dice-rolling app). That seems to be easy enough to represent with a base AnyRandomSource protocol, with sub-protocols RandomSource and PseudorandomSource (or whatever else seems to be a better name).

I think that there needs to be discussion about the random range for the static `random` properties. Right now, it can't return negative values, even for signed types. I feel that a random property on a type should use the entire domain of that type, and the range random properties can be used when you want a specific domain of values. If people aren't sure what Int.random or Double.random gets them, they won't use it, so I'd go for the simplest and most uniform possible definition for them: any finite value that the type can represent. (Also, your FixedWithInteger currently can't return Self.max, which I think is a bug.)

I have more comments, but it's getting late, so maybe I'll continue tomorrow.

Félix

···

Le 25 sept. 2017 à 21:57, Alejandro Alonso via swift-evolution <swift-evolution@swift.org> a écrit :

Hello evolution,

I am very thankful for all the feedback, and I’ve been working on a design that tries to utilize everybody’s ideas. The link to what I have so far is here: https://gist.github.com/Azoy/15f0518df38df9b722d4cb17bafea4c1. Please keep in mind this is just a design, no actual implementation as I would most likely need assistance in doing. The default source for randomness will use the OS’s unseeded CSPRNG. This current setup exposes developers to an API that lets them create their own RandomSources on the fly. I want to make the distinction that any existing or new sources of randomness that conform to UnsafeRandomSource are to be considered non cryptographically secure.

I would love to get this discussion flowing again, and I would love input on the design. A few things I came across with this design is that some may want to use ranges as an argument for the numeric types, RandomAccessCollection returning an optional when getting a random, and how to incorporate an API that allows distributions. I wanted to get input on how you feel about each of these topics as I’m indifferent about them all. I’m in no way saying this is the design we should go for, but I’m simply providing something I think we should build on or talk about.

- Alejandro

On Sep 8, 2017, 11:52 AM -0500, Alejandro Alonso via swift-evolution <swift-evolution@swift.org>, wrote:

Hello swift evolution, I would like to propose a unified approach to `random()` in Swift. I have a simple implementation here https://gist.github.com/Azoy/5d294148c8b97d20b96ee64f434bb4f5. This implementation is a simple wrapper over existing random functions so existing code bases will not be affected. Also, this approach introduces a new random feature for Linux users that give them access to upper bounds, as well as a lower bound for both Glibc and Darwin users. This change would be implemented within Foundation.

I believe this simple change could have a very positive impact on new developers learning Swift and experienced developers being able to write single random declarations.

I’d like to hear about your ideas on this proposal, or any implementation changes if need be.

- Alejando

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Instead of “UnsafeRandomSource”, I would call it “ReproducibleRandomSource”. I have also found that you often need to be able to “rewind” a reproducible random source for graphics applications:

  protocol ReproducibleRandomSource : RandomSource {
    init(seed: UInt64)
    func mark()->Int
    func returnToMark(_ mark:Int) //These could use something like an index instead of Int. My version just returns 1 the first time you call mark(), 2 the second time, etc...
  }

Also, I find that there are just a few primitive types I actually need from a random source:

• Double (full coverage of possible values)
• Double (in range of 0…1)
• UInt32

The following are also nice to have (built from the above), and commonly used:

• Bool / CoinFlip
• Int (positive value)
• FixedWidthInteger (of various sizes. Full coverage of possible values)
• Character/String
• CGFloat

Any other type can be built from these building blocks. I have a RandomSourceCreatable protocol which allows exactly that. Once you have that, you can put a method on random source which allows you to create any conforming type:

  extension RandomSource {
    func next<T:RandomSourceCreatable>(_ type: T.Type)->T
  }

This is extremely useful to create colors, offsets, etc…

One thing we need to definitely consider are constraints which people may want on the random value. For example, should an Int be positive? Should it be in a certain range? I have a “constraints” parameter on my RandomSourceCreatable protocol to handle this, and it works well, but I am not 100% happy with the ergonomics. I also have a variant with an “in range:” parameter that works for simple linear types like Ints and Floats. We could do something like:

  extension RandomSource {
    func next<T:RandomRangeCreatable>(_ type: T.Type, in range: ClosedRange<T>) -> T
  }

Finally, don’t underestimate the usefulness of coinFlip and func oneIn(_ number:UInt)->Bool. They let you quickly branch based on a random value:

  if source.oneIn(100) { //This will be true roughly 1 in 100 times
    //Do something occasionally
  }

Thanks,
Jon

···

On Sep 25, 2017, at 9:57 PM, Alejandro Alonso via swift-evolution <swift-evolution@swift.org> wrote:

Hello evolution,

I am very thankful for all the feedback, and I’ve been working on a design that tries to utilize everybody’s ideas. The link to what I have so far is here: https://gist.github.com/Azoy/15f0518df38df9b722d4cb17bafea4c1. Please keep in mind this is just a design, no actual implementation as I would most likely need assistance in doing. The default source for randomness will use the OS’s unseeded CSPRNG. This current setup exposes developers to an API that lets them create their own RandomSources on the fly. I want to make the distinction that any existing or new sources of randomness that conform to UnsafeRandomSource are to be considered non cryptographically secure.

I would love to get this discussion flowing again, and I would love input on the design. A few things I came across with this design is that some may want to use ranges as an argument for the numeric types, RandomAccessCollection returning an optional when getting a random, and how to incorporate an API that allows distributions. I wanted to get input on how you feel about each of these topics as I’m indifferent about them all. I’m in no way saying this is the design we should go for, but I’m simply providing something I think we should build on or talk about.

- Alejandro

On Sep 8, 2017, 11:52 AM -0500, Alejandro Alonso via swift-evolution <swift-evolution@swift.org>, wrote:

Hello swift evolution, I would like to propose a unified approach to `random()` in Swift. I have a simple implementation here https://gist.github.com/Azoy/5d294148c8b97d20b96ee64f434bb4f5. This implementation is a simple wrapper over existing random functions so existing code bases will not be affected. Also, this approach introduces a new random feature for Linux users that give them access to upper bounds, as well as a lower bound for both Glibc and Darwin users. This change would be implemented within Foundation.

I believe this simple change could have a very positive impact on new developers learning Swift and experienced developers being able to write single random declarations.

I’d like to hear about your ideas on this proposal, or any implementation changes if need be.

- Alejando

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

To throw an idea out into the wild: How about a protocol to define the default source fo random on a given platform, with per-platform extensions to provide default implementations?

This would allow any eventual proposal to have default arguments for functions— or to use within `var`s— without implicitly annotating one (CS)PRNG as the de-facto RNG for Swift on all platforms, as well as remove the requirement for providing a `shared` singleton on every (CS)PRNG.

I’m imagining something like this (names taken from, or inspired by, Félix’s design for consistency within this discussion, I’m not strongly attached to any of them):

protocol StandardRandomSource {
	static var generator: RandomSource { get }
}

extension StandardRandomSource {
	static var generator: RandomSource {
#if os(Linux)
		// /dev/random chosen naively
		return DeviceRandom.shared
#elseif os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
		// SecCopyRandomBytes-based, also chosen naively
		return SecRandomSource()
#else
		fatalError("Standard source of randomness not provided on current platform")
#endif
	}
}

and this new protocol could be used like this (largely copied from Félix’s design):

extension Randomizable {
	public static var random: Self {
		return random(using: StandardRandomSource.generator)
	}
}

extension FixedWidthInteger: {
	public static func random(using source: RandomSource = StandardRandomSource.generator) -> Self {
		return (0 ..< Self.max).random(using: source)
	}
}

On a more meta level, introducing this protocol lets us (Swift Evolution) kick the question of “What (CS)PRNG gets implemented for a given OS as the default provider?” further down the road instead of potentially blocking discussion for a long time.

Another possible upside that I can think of is: We could let per-platform implementations of this protocol could happen outside of the Swift Evolution process. Hopefully this means it would be easier to amend or fix in the future, as new platforms are added and new best practices arise.

A downside to this idea is that we’d be adding a protocol to the stdlib that isn’t intended for people to implement, although there’s no possible harm if anyone does so.

One other idea I also explored, but ultimately decided against was having per-platform `typealias`es instead of a protocol with a default implementation. Without a way to get an instance of a random number generator, I fell back to requiring `var shared: Self` to stay in `RandomSource`, which didn’t seem as necessary.

-z

···

On Sep 25, 2017, at 9:57 PM, Alejandro Alonso via swift-evolution <swift-evolution@swift.org> wrote:

Hello evolution,

I am very thankful for all the feedback, and I’ve been working on a design that tries to utilize everybody’s ideas. The link to what I have so far is here: https://gist.github.com/Azoy/15f0518df38df9b722d4cb17bafea4c1. Please keep in mind this is just a design, no actual implementation as I would most likely need assistance in doing. The default source for randomness will use the OS’s unseeded CSPRNG. This current setup exposes developers to an API that lets them create their own RandomSources on the fly. I want to make the distinction that any existing or new sources of randomness that conform to UnsafeRandomSource are to be considered non cryptographically secure.

I would love to get this discussion flowing again, and I would love input on the design. A few things I came across with this design is that some may want to use ranges as an argument for the numeric types, RandomAccessCollection returning an optional when getting a random, and how to incorporate an API that allows distributions. I wanted to get input on how you feel about each of these topics as I’m indifferent about them all. I’m in no way saying this is the design we should go for, but I’m simply providing something I think we should build on or talk about.

- Alejandro

On Sep 8, 2017, 11:52 AM -0500, Alejandro Alonso via swift-evolution <swift-evolution@swift.org>, wrote:
Hello swift evolution, I would like to propose a unified approach to `random()` in Swift. I have a simple implementation here https://gist.github.com/Azoy/5d294148c8b97d20b96ee64f434bb4f5. This implementation is a simple wrapper over existing random functions so existing code bases will not be affected. Also, this approach introduces a new random feature for Linux users that give them access to upper bounds, as well as a lower bound for both Glibc and Darwin users. This change would be implemented within Foundation.

I believe this simple change could have a very positive impact on new developers learning Swift and experienced developers being able to write single random declarations.

I’d like to hear about your ideas on this proposal, or any implementation changes if need be.

- Alejando

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

First of all, I like this proposal.

For a empty RandomAccessCollection, is it cause a fatal error with calling the random methods?

···

Alejandro Alonso via swift-evolution <swift-evolution@swift.org> 於 2017年9月26日 下午12:57 寫道:

Hello evolution,

I am very thankful for all the feedback, and I’ve been working on a design that tries to utilize everybody’s ideas. The link to what I have so far is here: https://gist.github.com/Azoy/15f0518df38df9b722d4cb17bafea4c1. Please keep in mind this is just a design, no actual implementation as I would most likely need assistance in doing. The default source for randomness will use the OS’s unseeded CSPRNG. This current setup exposes developers to an API that lets them create their own RandomSources on the fly. I want to make the distinction that any existing or new sources of randomness that conform to UnsafeRandomSource are to be considered non cryptographically secure.

I would love to get this discussion flowing again, and I would love input on the design. A few things I came across with this design is that some may want to use ranges as an argument for the numeric types, RandomAccessCollection returning an optional when getting a random, and how to incorporate an API that allows distributions. I wanted to get input on how you feel about each of these topics as I’m indifferent about them all. I’m in no way saying this is the design we should go for, but I’m simply providing something I think we should build on or talk about.

- Alejandro

On Sep 8, 2017, 11:52 AM -0500, Alejandro Alonso via swift-evolution <swift-evolution@swift.org>, wrote:
Hello swift evolution, I would like to propose a unified approach to `random()` in Swift. I have a simple implementation here https://gist.github.com/Azoy/5d294148c8b97d20b96ee64f434bb4f5. This implementation is a simple wrapper over existing random functions so existing code bases will not be affected. Also, this approach introduces a new random feature for Linux users that give them access to upper bounds, as well as a lower bound for both Glibc and Darwin users. This change would be implemented within Foundation.

I believe this simple change could have a very positive impact on new developers learning Swift and experienced developers being able to write single random declarations.

I’d like to hear about your ideas on this proposal, or any implementation changes if need be.

- Alejando

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Is there a link to the writeup? The one in the quote 404s.

Thanks,
Jon

···

On Nov 5, 2017, at 2:10 PM, Alejandro Alonso via swift-evolution <swift-evolution@swift.org> wrote:

Hello once again Swift evolution community. I have taken the time to write up the proposal for this thread, and have provided an implementation for it as well. I hope to once again get good feedback on the overall proposal.

- Alejandro

On Sep 8, 2017, 11:52 AM -0500, Alejandro Alonso via swift-evolution <swift-evolution@swift.org>, wrote:

Hello swift evolution, I would like to propose a unified approach to `random()` in Swift. I have a simple implementation here https://gist.github.com/Azoy/5d294148c8b97d20b96ee64f434bb4f5. This implementation is a simple wrapper over existing random functions so existing code bases will not be affected. Also, this approach introduces a new random feature for Linux users that give them access to upper bounds, as well as a lower bound for both Glibc and Darwin users. This change would be implemented within Foundation.

I believe this simple change could have a very positive impact on new developers learning Swift and experienced developers being able to write single random declarations.

I’d like to hear about your ideas on this proposal, or any implementation changes if need be.

- Alejando

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

For the proof of concept, I had accidentally deleted that one. I have a more up to date one which was discussed a few weeks later. https://gist.github.com/Azoy/15f0518df38df9b722d4cb17bafea4c1

- Alejandro

···

On Nov 5, 2017, 4:37 PM -0600, Jonathan Hull <jhull@gbis.com>, wrote:
Is there a link to the writeup? The one in the quote 404s.

Thanks,
Jon

On Nov 5, 2017, at 2:10 PM, Alejandro Alonso via swift-evolution <swift-evolution@swift.org<mailto:swift-evolution@swift.org>> wrote:

Hello once again Swift evolution community. I have taken the time to write up the proposal for this thread, and have provided an implementation for it as well. I hope to once again get good feedback on the overall proposal.

- Alejandro

On Sep 8, 2017, 11:52 AM -0500, Alejandro Alonso via swift-evolution <swift-evolution@swift.org<mailto:swift-evolution@swift.org>>, wrote:
Hello swift evolution, I would like to propose a unified approach to `random()` in Swift. I have a simple implementation here https://gist.github.com/Azoy/5d294148c8b97d20b96ee64f434bb4f5. This implementation is a simple wrapper over existing random functions so existing code bases will not be affected. Also, this approach introduces a new random feature for Linux users that give them access to upper bounds, as well as a lower bound for both Glibc and Darwin users. This change would be implemented within Foundation.

I believe this simple change could have a very positive impact on new developers learning Swift and experienced developers being able to write single random declarations.

I’d like to hear about your ideas on this proposal, or any implementation changes if need be.

- Alejando

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org<mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

Hello swift evolution once again, I’ve been hard at work considering every
email and revising the proposal. I’ve made lots of changes and additions to
the proposal to discuss some problems we’ve had (T.random), and walks
through detailed design. You can see the proposal here:
https://github.com/apple/swift-evolution/pull/760 .

A big issue that lots of people pointed out was `T.random %` and to remove
it completely from the API. To give a gist of why I continue to support
T.random:

1. Modulo bias misuse is only a problem to types that conform to
`BinaryInteger`. Why remove this functionality if only a portion of the
types have the ability of misuse. `Double.random % 10` is a good example of
where modulo isn’t implemented here as it produces the error, “'%' is
unavailable: Use truncatingRemainder instead”.

2. `Int.random(in: Int.min … Int.max)` doesn’t work. For developers that
actually rely on this functionality, the work around that was discussed
earlier simply doesn’t work. `Int.min … Int.max`’s count property exceeds
that of `Int`’s numerical range. A working work around would be something
along the lines of `Int(truncatingIfNeeded: Random.default.next(UInt.self))`
which creates a pain point for those developers. As the goal of this
proposal to remove pain points regarding random, this change does the
opposite.

I’m interested to hear if anymore discussion around this, or any other
issues come up.

There is no reason why `(Int.min...Int.max).random` (as I believe the
consensus suggestion was) "doesn't work." Certainly, it doesn't work if you
write only a default implementation on Collection. But `Range where Bound :
FixedWidthInteger & SignedInteger` should have its own implementation of
`random` anyway (for performance reasons, if nothing else) and there is no
impediment to a working implementation.

As to your first point: as evidenced by concrete data given by others
above, the overwhelming majority of uses of `random %` appear to be
erroneous, and of course the great majority of uses of `T.random` will be
on types that conform to `BinaryInteger`. Again, I repeat my concern that
you are naming multiple distinct things "random", which is making it
difficult to carry on this discussion. `BinaryInteger.random` is distinct
in its semantics, and this is precisely the method that is often used and
often misused. There is no reason why other things that you name "random"
shouldn't exist just because `BinaryInteger` shouldn't have a method named
`random`, and it's spurious to say "why remove this functionality if only a
portion of the types have the ability of misuse," when this _functionality_
and its misuse are specific to `BinaryInteger`.

···

On Tue, Jan 2, 2018 at 2:35 AM, Alejandro Alonso via swift-evolution < swift-evolution@swift.org> wrote:

On Sep 8, 2017, 11:52 AM -0500, Alejandro Alonso via swift-evolution < > swift-evolution@swift.org>, wrote:

Hello swift evolution, I would like to propose a unified approach to
`random()` in Swift. I have a simple implementation here
https://gist.github.com/Azoy/5d294148c8b97d20b96ee64f434bb4f5. This
implementation is a simple wrapper over existing random functions so
existing code bases will not be affected. Also, this approach introduces a
new random feature for Linux users that give them access to upper bounds,
as well as a lower bound for both Glibc and Darwin users. This change would
be implemented within Foundation.

I believe this simple change could have a very positive impact on new
developers learning Swift and experienced developers being able to write
single random declarations.

I’d like to hear about your ideas on this proposal, or any implementation
changes if need be.

- Alejando

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Just skimmed through the updated proposal and am weighing in with my naïve opinions:

I’m still highly skeptical of a static “T.random” API. I’ve yet to see a convincing example where it’d be useful to pick a value from the range of all possible values. The only truly useful one I’ve seen is “pick a random bool”, which could easily be done via “[true, false].random()"

I much prefer the GameplayKit API[0], which breaks the idea of randomness up in to 2 separate concepts:
A “Source” → Where the random numbers come from
A “Distribution” → Initialized with a source, it makes sure the produced numbers exhibit a specific distribution over multiple samplings. Ie, a uniform distribution vs a Gaussian distribution, or something like “I want to pick a card from a deck but bias choices towards Spades or Aces”. I’m also reminded of the anecdote of how iTunes had to modify their “playlist shuffle” algorithm to be less random[1], because the true randomness would do weird things that made it seem not random. Spotify had the same problem and solution[2].
Breaking things up like this would also make it easier to test randomness (by using a replay-able source) but that still follow the parameters of your app (that it has a bell-curve distribution of probabilities, for example)

I’d still really really really like to see how this could be done as two separate things:
A minimal implementation in the Standard Library (like, defining the base Source and Distribution protocols, with a single default implementation of each)
A proposal for a more complete “non-standard library” where the larger array of functionality would be contained. For example, IMO I don’t think the shuffling stuff needs to be in the standard library. This is also where all the cryptographically secure stuff (that your typical app developer does not need) would live.

The “random” element of a collection/range should be “func random() → Element?”, not “var random: Element?”. Property values shouldn't change between accesses. Ditto the static “Randomizable.random” property.

What do you think about actively discouraging people from using the modulo operator to create a range? It could be done by having the RNGs return a “RandomValue<T>” type, then defining a mod operator that takes a RandomValue<T> and a T (?), and then giving it a deprecation warning + fixit. Not sure if that’d be worth the type overhead, but I’m very much in favor of encouraging people towards better practices.

I’m +1 on crashing if we can’t produce a random number.

What do you think about the philosophical difference of Type.random(using:) vs Type.init(randomSource:)?

Dave

[0]: https://developer.apple.com/documentation/gameplaykit/gkrandom
[1]: https://www.youtube.com/watch?v=lg188Ebas9E&feature=youtu.be&t=719 <https://www.youtube.com/watch?v=lg188Ebas9E&feature=youtu.be&t=719>
[2]: https://labs.spotify.com/2014/02/28/how-to-shuffle-songs/

···

On Jan 2, 2018, at 1:35 AM, Alejandro Alonso via swift-evolution <swift-evolution@swift.org> wrote:

Hello swift evolution once again, I’ve been hard at work considering every email and revising the proposal. I’ve made lots of changes and additions to the proposal to discuss some problems we’ve had (T.random), and walks through detailed design. You can see the proposal here: https://github.com/apple/swift-evolution/pull/760 .

A big issue that lots of people pointed out was `T.random %` and to remove it completely from the API. To give a gist of why I continue to support T.random:

1. Modulo bias misuse is only a problem to types that conform to `BinaryInteger`. Why remove this functionality if only a portion of the types have the ability of misuse. `Double.random % 10` is a good example of where modulo isn’t implemented here as it produces the error, “'%' is unavailable: Use truncatingRemainder instead”.

2. `Int.random(in: Int.min … Int.max)` doesn’t work. For developers that actually rely on this functionality, the work around that was discussed earlier simply doesn’t work. `Int.min … Int.max`’s count property exceeds that of `Int`’s numerical range. A working work around would be something along the lines of `Int(truncatingIfNeeded: Random.default.next(UInt.self))` which creates a pain point for those developers. As the goal of this proposal to remove pain points regarding random, this change does the opposite.

I’m interested to hear if anymore discussion around this, or any other issues come up.

- Alejandro

On Sep 8, 2017, 11:52 AM -0500, Alejandro Alonso via swift-evolution <swift-evolution@swift.org>, wrote:

Hello swift evolution, I would like to propose a unified approach to `random()` in Swift. I have a simple implementation here https://gist.github.com/Azoy/5d294148c8b97d20b96ee64f434bb4f5. This implementation is a simple wrapper over existing random functions so existing code bases will not be affected. Also, this approach introduces a new random feature for Linux users that give them access to upper bounds, as well as a lower bound for both Glibc and Darwin users. This change would be implemented within Foundation.

I believe this simple change could have a very positive impact on new developers learning Swift and experienced developers being able to write single random declarations.

I’d like to hear about your ideas on this proposal, or any implementation changes if need be.

- Alejando

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Hi Alejandro,

I’m really happy to see someone pick this up. We had suggested some kind of random support could be a goal for addition to the standard library in Swift 4 phase 2 but didn’t manage it, so I definitely think a good proposal would be given consideration for Swift 5.

Regarding the implementation – I would suggest exploring something along the lines of an extension on RandomAccessCollection that adds a property for a random element, rather than a pair of free functions. This would have a number of benefits:

- a very common use case is picking a random entry from a collection, which this would do automatically
- it gives you a very natural way of expressing a ranged random number i.e. (0..<10).randomElement (not necessarily recommending that name btw, it’s one of various possibilities)
- since both kinds of countable ranges are collections, it sidesteps that issue :slight_smile:
- it allows for multiple different integers without the need for casting i.e. in the above, if type context meant the result was a UInt16, that’s what it would be

The one downside is that you’d have to write (0..<Int.max). This might be a justification for a static property on one of the Integer protocols as shorthand for that.

The tricky part (in addition to the cross-platform aspect) is ensuring correct distribution across the possible distances. But since this is something that people might easily get wrong, that reinforces the idea of this being something that’s easy to use correctly in the std lib.

I’d also suggest proposing a shuffle implementation for RandomAccessCollection+MutableCollection at the same time (probably as a separate but linked proposal), since this is also something that is often requested, easy to get wrong, and needs a cross-platform source of random numbers.

Regards,
Ben

···

On Sep 8, 2017, at 10:34 AM, Alejandro Alonso via swift-evolution <swift-evolution@swift.org> wrote:

Range support is something that came up, and I think it’s a great idea as well. My question now is do we support both `CountableRange` and `CountableClosedRange`?

On Sep 8, 2017, 12:08 PM -0500, Shawn Erickson <shawnce@gmail.com>, wrote:

It would be nice to leverage range support instead of a start and end value IMHO.
On Fri, Sep 8, 2017 at 9:52 AM Alejandro Alonso via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Hello swift evolution, I would like to propose a unified approach to `random()` in Swift. I have a simple implementation here https://gist.github.com/Azoy/5d294148c8b97d20b96ee64f434bb4f5. This implementation is a simple wrapper over existing random functions so existing code bases will not be affected. Also, this approach introduces a new random feature for Linux users that give them access to upper bounds, as well as a lower bound for both Glibc and Darwin users. This change would be implemented within Foundation.

I believe this simple change could have a very positive impact on new developers learning Swift and experienced developers being able to write single random declarations.

I’d like to hear about your ideas on this proposal, or any implementation changes if need be.

- Alejando

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

I think ClosedRange. Also there should be support for floating types.

···

On Sep 8, 2017, at 12:34 PM, Alejandro Alonso via swift-evolution <swift-evolution@swift.org> wrote:

Range support is something that came up, and I think it’s a great idea as well. My question now is do we support both `CountableRange` and `CountableClosedRange`?

On Sep 8, 2017, 12:08 PM -0500, Shawn Erickson <shawnce@gmail.com>, wrote:
It would be nice to leverage range support instead of a start and end value IMHO.

On Fri, Sep 8, 2017 at 9:52 AM Alejandro Alonso via swift-evolution <swift-evolution@swift.org> wrote:
Hello swift evolution, I would like to propose a unified approach to `random()` in Swift. I have a simple implementation here https://gist.github.com/Azoy/5d294148c8b97d20b96ee64f434bb4f5. This implementation is a simple wrapper over existing random functions so existing code bases will not be affected. Also, this approach introduces a new random feature for Linux users that give them access to upper bounds, as well as a lower bound for both Glibc and Darwin users. This change would be implemented within Foundation.

I believe this simple change could have a very positive impact on new developers learning Swift and experienced developers being able to write single random declarations.

I’d like to hear about your ideas on this proposal, or any implementation changes if need be.

- Alejando

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Huge +1 to stdlib (or even Foundation) random number generator. I’ve worked with random numbers on both Linux and macOS/iOS and have found myself annoyed with the lack of easy random number generators. It seems that implementing a pure Swift RNG would be an obviously good addition to the stdlib.

I don’t think that it would be possible to make this work for floating point numbers. Although admittedly, I know very little about Floating Point numbers. I think this is still a worthwhile addition to Swift even for just Integers alone.

···

On Sep 8, 2017, at 1:30 PM, Ben Cohen via swift-evolution <swift-evolution@swift.org> wrote:

Hi Alejandro,

I’m really happy to see someone pick this up. We had suggested some kind of random support could be a goal for addition to the standard library in Swift 4 phase 2 but didn’t manage it, so I definitely think a good proposal would be given consideration for Swift 5.

Regarding the implementation – I would suggest exploring something along the lines of an extension on RandomAccessCollection that adds a property for a random element, rather than a pair of free functions. This would have a number of benefits:

- a very common use case is picking a random entry from a collection, which this would do automatically
- it gives you a very natural way of expressing a ranged random number i.e. (0..<10).randomElement (not necessarily recommending that name btw, it’s one of various possibilities)
- since both kinds of countable ranges are collections, it sidesteps that issue :slight_smile:
- it allows for multiple different integers without the need for casting i.e. in the above, if type context meant the result was a UInt16, that’s what it would be

The one downside is that you’d have to write (0..<Int.max). This might be a justification for a static property on one of the Integer protocols as shorthand for that.

The tricky part (in addition to the cross-platform aspect) is ensuring correct distribution across the possible distances. But since this is something that people might easily get wrong, that reinforces the idea of this being something that’s easy to use correctly in the std lib.

I’d also suggest proposing a shuffle implementation for RandomAccessCollection+MutableCollection at the same time (probably as a separate but linked proposal), since this is also something that is often requested, easy to get wrong, and needs a cross-platform source of random numbers.

Regards,
Ben

On Sep 8, 2017, at 10:34 AM, Alejandro Alonso via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Range support is something that came up, and I think it’s a great idea as well. My question now is do we support both `CountableRange` and `CountableClosedRange`?

On Sep 8, 2017, 12:08 PM -0500, Shawn Erickson <shawnce@gmail.com <mailto:shawnce@gmail.com>>, wrote:

It would be nice to leverage range support instead of a start and end value IMHO.
On Fri, Sep 8, 2017 at 9:52 AM Alejandro Alonso via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Hello swift evolution, I would like to propose a unified approach to `random()` in Swift. I have a simple implementation here https://gist.github.com/Azoy/5d294148c8b97d20b96ee64f434bb4f5. This implementation is a simple wrapper over existing random functions so existing code bases will not be affected. Also, this approach introduces a new random feature for Linux users that give them access to upper bounds, as well as a lower bound for both Glibc and Darwin users. This change would be implemented within Foundation.

I believe this simple change could have a very positive impact on new developers learning Swift and experienced developers being able to write single random declarations.

I’d like to hear about your ideas on this proposal, or any implementation changes if need be.

- Alejando

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

What if we did it with something like this:

protocol RandomGenerator {
  associated type T: Numeric // Since numeric types are the only kinds where we could get a random number?
  func uniform() -> T
  // Other random type functions...
}

I support a protocol, but not one with an associated type; those are an enormous pain in the rear to work with. They're quite probably my biggest gripe with Swift (and it's not a short list). I shouldn't have to make an entire class generic just so I can have an RNG that I'll probably want to be a private field anyway.

···

On Sep 8, 2017, at 2:46 PM, Jacob Williams via swift-evolution <swift-evolution@swift.org> wrote:

Although if we didn’t constrain T to Numeric then collections could also conform to it, although I’m not sure that collections would want to directly conform to this. There may need to be a separate protocol for types with Numeric indexes?

I’m no pro and really haven’t thought about this too deeply. Mostly just spitballing/brainstorming.

On Sep 8, 2017, at 3:03 PM, Jacob Williams via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Huge +1 to stdlib (or even Foundation) random number generator. I’ve worked with random numbers on both Linux and macOS/iOS and have found myself annoyed with the lack of easy random number generators. It seems that implementing a pure Swift RNG would be an obviously good addition to the stdlib.

I don’t think that it would be possible to make this work for floating point numbers. Although admittedly, I know very little about Floating Point numbers. I think this is still a worthwhile addition to Swift even for just Integers alone.

On Sep 8, 2017, at 1:30 PM, Ben Cohen via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Hi Alejandro,

I’m really happy to see someone pick this up. We had suggested some kind of random support could be a goal for addition to the standard library in Swift 4 phase 2 but didn’t manage it, so I definitely think a good proposal would be given consideration for Swift 5.

Regarding the implementation – I would suggest exploring something along the lines of an extension on RandomAccessCollection that adds a property for a random element, rather than a pair of free functions. This would have a number of benefits:

- a very common use case is picking a random entry from a collection, which this would do automatically
- it gives you a very natural way of expressing a ranged random number i.e. (0..<10).randomElement (not necessarily recommending that name btw, it’s one of various possibilities)
- since both kinds of countable ranges are collections, it sidesteps that issue :slight_smile:
- it allows for multiple different integers without the need for casting i.e. in the above, if type context meant the result was a UInt16, that’s what it would be

The one downside is that you’d have to write (0..<Int.max). This might be a justification for a static property on one of the Integer protocols as shorthand for that.

The tricky part (in addition to the cross-platform aspect) is ensuring correct distribution across the possible distances. But since this is something that people might easily get wrong, that reinforces the idea of this being something that’s easy to use correctly in the std lib.

I’d also suggest proposing a shuffle implementation for RandomAccessCollection+MutableCollection at the same time (probably as a separate but linked proposal), since this is also something that is often requested, easy to get wrong, and needs a cross-platform source of random numbers.

Regards,
Ben

On Sep 8, 2017, at 10:34 AM, Alejandro Alonso via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Range support is something that came up, and I think it’s a great idea as well. My question now is do we support both `CountableRange` and `CountableClosedRange`?

On Sep 8, 2017, 12:08 PM -0500, Shawn Erickson <shawnce@gmail.com <mailto:shawnce@gmail.com>>, wrote:

It would be nice to leverage range support instead of a start and end value IMHO.
On Fri, Sep 8, 2017 at 9:52 AM Alejandro Alonso via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Hello swift evolution, I would like to propose a unified approach to `random()` in Swift. I have a simple implementation here https://gist.github.com/Azoy/5d294148c8b97d20b96ee64f434bb4f5. This implementation is a simple wrapper over existing random functions so existing code bases will not be affected. Also, this approach introduces a new random feature for Linux users that give them access to upper bounds, as well as a lower bound for both Glibc and Darwin users. This change would be implemented within Foundation.

I believe this simple change could have a very positive impact on new developers learning Swift and experienced developers being able to write single random declarations.

I’d like to hear about your ideas on this proposal, or any implementation changes if need be.

- Alejando

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

What if we did it with something like this:

protocol RandomGenerator {
  associated type T: Numeric // Since numeric types are the only kinds where we could get a random number?
  func uniform() -> T
  // Other random type functions...
}

Although if we didn’t constrain T to Numeric then collections could also conform to it, although I’m not sure that collections would want to directly conform to this. There may need to be a separate protocol for types with Numeric indexes?

I’m no pro and really haven’t thought about this too deeply. Mostly just spitballing/brainstorming.

···

On Sep 8, 2017, at 3:03 PM, Jacob Williams via swift-evolution <swift-evolution@swift.org> wrote:

Huge +1 to stdlib (or even Foundation) random number generator. I’ve worked with random numbers on both Linux and macOS/iOS and have found myself annoyed with the lack of easy random number generators. It seems that implementing a pure Swift RNG would be an obviously good addition to the stdlib.

I don’t think that it would be possible to make this work for floating point numbers. Although admittedly, I know very little about Floating Point numbers. I think this is still a worthwhile addition to Swift even for just Integers alone.

On Sep 8, 2017, at 1:30 PM, Ben Cohen via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Hi Alejandro,

I’m really happy to see someone pick this up. We had suggested some kind of random support could be a goal for addition to the standard library in Swift 4 phase 2 but didn’t manage it, so I definitely think a good proposal would be given consideration for Swift 5.

Regarding the implementation – I would suggest exploring something along the lines of an extension on RandomAccessCollection that adds a property for a random element, rather than a pair of free functions. This would have a number of benefits:

- a very common use case is picking a random entry from a collection, which this would do automatically
- it gives you a very natural way of expressing a ranged random number i.e. (0..<10).randomElement (not necessarily recommending that name btw, it’s one of various possibilities)
- since both kinds of countable ranges are collections, it sidesteps that issue :slight_smile:
- it allows for multiple different integers without the need for casting i.e. in the above, if type context meant the result was a UInt16, that’s what it would be

The one downside is that you’d have to write (0..<Int.max). This might be a justification for a static property on one of the Integer protocols as shorthand for that.

The tricky part (in addition to the cross-platform aspect) is ensuring correct distribution across the possible distances. But since this is something that people might easily get wrong, that reinforces the idea of this being something that’s easy to use correctly in the std lib.

I’d also suggest proposing a shuffle implementation for RandomAccessCollection+MutableCollection at the same time (probably as a separate but linked proposal), since this is also something that is often requested, easy to get wrong, and needs a cross-platform source of random numbers.

Regards,
Ben

On Sep 8, 2017, at 10:34 AM, Alejandro Alonso via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Range support is something that came up, and I think it’s a great idea as well. My question now is do we support both `CountableRange` and `CountableClosedRange`?

On Sep 8, 2017, 12:08 PM -0500, Shawn Erickson <shawnce@gmail.com <mailto:shawnce@gmail.com>>, wrote:

It would be nice to leverage range support instead of a start and end value IMHO.
On Fri, Sep 8, 2017 at 9:52 AM Alejandro Alonso via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Hello swift evolution, I would like to propose a unified approach to `random()` in Swift. I have a simple implementation here https://gist.github.com/Azoy/5d294148c8b97d20b96ee64f434bb4f5. This implementation is a simple wrapper over existing random functions so existing code bases will not be affected. Also, this approach introduces a new random feature for Linux users that give them access to upper bounds, as well as a lower bound for both Glibc and Darwin users. This change would be implemented within Foundation.

I believe this simple change could have a very positive impact on new developers learning Swift and experienced developers being able to write single random declarations.

I’d like to hear about your ideas on this proposal, or any implementation changes if need be.

- Alejando

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution