Re: [swift-evolution] [Proposal] Random Unification

2018-01-12 Thread Alejandro Alonso via swift-evolution
Done and done!

Sent from my iPhone

On Jan 12, 2018, at 01:22, Nate Cook 
> wrote:

On Jan 11, 2018, at 9:17 PM, Alejandro Alonso 
> wrote:

Sorry it takes me forever to respond! I finally got around to writing this! 
School really takes all my time x)

I have a few ideas on where we can go with this:

1. I agree, we should ditch `Randomizable` as something like that should belong 
in a separate library or written by the user.

2. I also agree we should ditch the associated type on `RandomNumberGenerator`. 
I think we can sacrifice 32 bit generators using 64 bit ints to conform to the 
core team’s general use policy. This also makes default arguments for rngs 
possible which is a +1 for me!

I start to drift off from your design because `.random()` being an exception to 
ranges in that it’s inconsistent with other collection facilities and 
collection `.random()`. You make a few emails in the past that reference this 
as well. I think the right move is to have the static functions utilize the 
ranges to provide non optional types.

You wrote:

“
I see a couple points in favor of these static methods (or initializers) on the 
numeric types:

1) The collection method will need to return an optional to match the semantics 
of existing methods (like min()). If this is the only method available, every 
time someone needs a random value in the range 1...10, they’ll need to unwrap 
the result (with either force unwrapping, which people will complain about, or 
some kind of conditional binding, which is its own problem). Even if the 
semantics are the same (trapping on an empty range), the user experience of 
using a non-optional method will be better.



2) Floating-point ranges won’t get the collection method, so either we’ll have 
inconsistent APIs (random FP value is non-optional, random integer is optional) 
or we’ll make the FP API optional just to match. Both of those seem bad.
”

I believe this is the direction we need to go to keep consistency with 
collection based methods by justifying `.random(in:)` on the numeric types. 
With that in mind, Ben made a comment a long while ago saying, “The one 
downside is that you’d have to write 0..mailto:swift-evolution@swift.org>>, wrote:
I created a playground to explore this question, starting with a minimal subset 
of the proposal’s additions and building from there. The attached playground 
demonstrates what’s possible with this subset on the first page, then uses 
subsequent pages to explore how the main random facilities of the C++ STL work 
under this model. (In my opinion, they work pretty well!)

The subset in the playground has three main differences from the proposal:
 - It doesn't include a Randomizable protocol or a random property on numeric 
types.
 - It doesn't include the static random(in:) methods on numeric types, either.
 - The RandomNumberGenerator protocol doesn't have an associated type. Instead, 
it requires all conforming types to produce UInt64 values.

I’ve tried to include a bit of real-world usage in the playground to 
demonstrate what writing code would look like with these additions. Please take 
a look!

Nate


On Dec 2, 2017, at 9:50 PM, Dave Abrahams via swift-evolution 
> wrote:

I don’t have much to say about this other than that I think the discussion 
seems way too narrow, focusing on spelling rather than on functionality and 
composability.  I consider the “generic random number library” design to be a 
mostly-solved problem, in the C++ standard library 
(http://en.cppreference.com/w/cpp/numeric/random).  Whatever goes into the 
Swift standard library does not need to have all those features right away, but 
should support being extended into something having the same general shape. IMO 
the right design strategy is to implement and use a Swift version of C++’s 
facilities and only then consider proposing [perhaps a subset of] that design 
for standardization in Swift.

Sent from my iPad

On Dec 2, 2017, at 5:12 PM, Kyle Murray via swift-evolution 
> wrote:


On Dec 2, 2017, at 6:02 PM, Xiaodi Wu via swift-evolution 
> wrote:

Instead, we ought to make clear to users both the features and the limitations 
of this API, to encourage use where suitable and to discourage use where 
unsuitable.

I like that you're considering the balance here. I've been lightly following 
this thread and want to add my thoughts on keeping crypto and pseudorandomness 
out of the name of at least one random API intended for general use.

For someone who doesn't know or care about the subtleties of insecure or 
pseudorandom numbers, I'm not sure that the name insecureRandom is effectively 
much different than badRandom, at least in terms of the information it conveys 
to 

Re: [swift-evolution] [Proposal] Random Unification

2018-01-12 Thread Alejandro Alonso via swift-evolution
Give up*

Sent from my iPhone

On Jan 12, 2018, at 08:10, Alejandro Alonso via swift-evolution 
<swift-evolution@swift.org<mailto:swift-evolution@swift.org>> wrote:

I am willing to give `.random()`. However I still wish to preserve 
`.random(in:)` and `.random()` on Bool.

Sent from my iPhone

On Jan 11, 2018, at 21:28, Xiaodi Wu 
<xiaodi...@gmail.com<mailto:xiaodi...@gmail.com>> wrote:

On Thu, Jan 11, 2018 at 9:17 PM, Alejandro Alonso via swift-evolution 
<swift-evolution@swift.org<mailto:swift-evolution@swift.org>> wrote:
Sorry it takes me forever to respond! I finally got around to writing this! 
School really takes all my time x)

I have a few ideas on where we can go with this:

1. I agree, we should ditch `Randomizable` as something like that should belong 
in a separate library or written by the user.

2. I also agree we should ditch the associated type on `RandomNumberGenerator`. 
I think we can sacrifice 32 bit generators using 64 bit ints to conform to the 
core team’s general use policy. This also makes default arguments for rngs 
possible which is a +1 for me!

I start to drift off from your design because `.random()` being an exception to 
ranges in that it’s inconsistent with other collection facilities and 
collection `.random()`. You make a few emails in the past that reference this 
as well. I think the right move is to have the static functions utilize the 
ranges to provide non optional types.

You wrote:

“
I see a couple points in favor of these static methods (or initializers) on the 
numeric types:

1) The collection method will need to return an optional to match the semantics 
of existing methods (like min()). If this is the only method available, every 
time someone needs a random value in the range 1...10, they’ll need to unwrap 
the result (with either force unwrapping, which people will complain about, or 
some kind of conditional binding, which is its own problem). Even if the 
semantics are the same (trapping on an empty range), the user experience of 
using a non-optional method will be better.



2) Floating-point ranges won’t get the collection method, so either we’ll have 
inconsistent APIs (random FP value is non-optional, random integer is optional) 
or we’ll make the FP API optional just to match. Both of those seem bad.
”

I believe this is the direction we need to go to keep consistency with 
collection based methods by justifying `.random(in:)` on the numeric types. 
With that in mind, Ben made a comment a long while ago saying, “The one 
downside is that you’d have to write 0..mailto:swift-evolution@swift.org>>, wrote:
I created a playground to explore this question, starting with a minimal subset 
of the proposal’s additions and building from there. The attached playground 
demonstrates what’s possible with this subset on the first page, then uses 
subsequent pages to explore how the main random facilities of the C++ STL work 
under this model. (In my opinion, they work pretty well!)

The subset in the playground has three main differences from the proposal:
 - It doesn't include a Randomizable protocol or a random property on numeric 
types.
 - It doesn't include the static random(in:) methods on numeric types, either.
 - The RandomNumberGenerator protocol doesn't have an associated type. Instead, 
it requires all conforming types to produce UInt64 values.

I’ve tried to include a bit of real-world usage in the playground to 
demonstrate what writing code would look like with these additions. Please take 
a look!

Nate


On Dec 2, 2017, at 9:50 PM, Dave Abrahams via swift-evolution 
<swift-evolution@swift.org<mailto:swift-evolution@swift.org>> wrote:

I don’t have much to say about this other than that I think the discussion 
seems way too narrow, focusing on spelling rather than on functionality and 
composability.  I consider the “generic random number library” design to be a 
mostly-solved problem, in the C++ standard library 
(http://en.cppreference.com/w/cpp/numeric/random).  Whatever goes into the 
Swift standard library does not need to have all those features right away, but 
should support being extended into something having the same general shape. IMO 
the right design strategy is to implement and use a Swift version of C++’s 
facilities and only then consider proposing [perhaps a subset of] that design 
for standardization in Swift.

Sent from my iPad

On Dec 2, 2017, at 5:12 PM, Kyle Murray via swift-evolution 
<swift-evolution@swift.org<mailto:swift-evolution@swift.org>> wrote:


On Dec 2, 2017, at 6:02 PM, Xiaodi Wu via swift-evolution 
<swift-evolution@swift.org<mailto:swift-evolution@swift.org>> wrote:

Instead, we ought to make clear to users both the features and the limitations 
of this API, to encourage use where suitable and to discourage use where 
unsuitable.

I like that you're considering the balance here. I've been lightly following 
this thread and w

Re: [swift-evolution] [Proposal] Random Unification

2018-01-12 Thread Alejandro Alonso via swift-evolution
(0 ..< 10).random() would return an optional
Int.random(in: 0 ..< 10) would return a non optional (this is the one that 
crashes on bad range)

Sent from my iPhone

On Jan 12, 2018, at 07:11, Letanyan Arumugam 
> wrote:

Nate’s design follows a consistent idea of getting a random value from some set 
of values. Adding the static method random() to a type essentially creates an 
implicit set which you yourself said leads to inconsistency (Double/Int). 
Secondly I don’t see why random(in:) should be added when it is just a 
different spelling for what is already provided. If my second statement is 
incorrect and there’s something I’m missing please correct me?

I think that consistency outweighs the random trapping inconsistency, however I 
would actually be fine if random returned an optional. Though the way random is 
used would likely lead to less opportunities for a trap than the other methods 
you mention.


Letanyan

On 12 Jan 2018, at 04:39, Alejandro Alonso 
> wrote:

If anything, Nate’s design is inconsistent as properties like `.first` and 
`.last` return an optional, and methods like `.min()` and `.max()` return an 
optional as well. Having `.random()` on ranges be an exception and return non 
optionals are inconsistent with other collection facilities, and with other 
collections that aren’t ranges that return optionals on `.random()`.

- Alejandro

On Jan 11, 2018, 12:06 PM -0600, Letanyan Arumugam via swift-evolution 
>, wrote:
This is really cool and seems very powerful. However I don’t think we should 
sacrifice consistency for extendability. Especially when the extendability 
would not be what most people need.

What I am basically trying to say is that. I think the proposals current design 
direction fits better in a Random library rather than the Standard Library. And 
Nate’s design more directly addresses the motivating points of the proposal.

Letanyan


Sure. Small disclaimer that this was originally written back in the Swift 1~2 
days, so it is overdue for a simplifying rewrite.

Also, I should point out that the term “Source” has a special meaning in my 
code.  It basically means that something will provide an ~infinite collection 
of values of a type T.   I have what I call a “ConstantSource” which just wraps 
a T and gives it back when asked.  But then I have a bunch of other “sources" 
which let you create repeating patterns and do deferred calculations and things 
like that.  Finally I have a “RandomSource” which is part of what started this 
discussion.  You set up a RandomSource with a set of constraints, and then it 
gives you random values of T that adhere to those constraints (e.g. colors with 
a range of hues but the same saturation) whenever you ask for them.

This is really useful for doing things like graphic effects because, for 
example, I can ask for a source of colors and a source of line widths and then 
get out a large variety of interesting patterns from the same algorithm.  I can 
make simple stripes with ConstantSources, or I can make repeating patterns of 
lines with repeating sources, or I can have random colors which look good 
together by using a RandomSource.  I can take a BezierPath and make it look 
hand-drawn by breaking it into a bunch of lines and then offset the points a 
small amount using a RandomSource of CGVectors.

Not sure how useful this concept of randomness (and pattern) is to others, but 
I find it immensely useful!  Not sure of the best way to implement it.  The way 
I do it is a type erased protocol with private conforming structs and then 
public initializers on the type-erasing box.  The end result is that I can just 
say:

let myConst = Source(1) //ConstantSource with 1 as a value
let myPattern = Source([1, 2]) //OrderedSource which repeats 1, then 2 over and 
over forever
let myMeta = Source([myConst, myPattern]) //Will alternate between sub-sources 
in order. Can be nested.
//…and so on.

It is quite extensible and can make very complex/interesting patterns very 
easily.  What I like about it is that (well controlled) random values and 
patterns or constant values can be interchanged very easily.

The RandomSource has a RandomSourceCreatable Protocol that lets it take random 
bits and turn them into objects/structs of T adhering to the given constraints. 
 This is way more complex under the hood than it needs to be, but it works well 
in practice, and I haven’t gotten around to cleaning it up yet:

public protocol RandomSourceCreatable {
associatedtype ConstraintType = Self

///This should be implimented by simple types without internal components
static func createRandom(rnd value:RandomSourceValue, 
constraint:RandomSourceConstraint)->Self

///This should be implimented by complex types with multiple axis of constraints
static func createRandom(rnd 

Re: [swift-evolution] [Proposal] Random Unification

2018-01-12 Thread Alejandro Alonso via swift-evolution
I am willing to give `.random()`. However I still wish to preserve 
`.random(in:)` and `.random()` on Bool.

Sent from my iPhone

On Jan 11, 2018, at 21:28, Xiaodi Wu 
<xiaodi...@gmail.com<mailto:xiaodi...@gmail.com>> wrote:

On Thu, Jan 11, 2018 at 9:17 PM, Alejandro Alonso via swift-evolution 
<swift-evolution@swift.org<mailto:swift-evolution@swift.org>> wrote:
Sorry it takes me forever to respond! I finally got around to writing this! 
School really takes all my time x)

I have a few ideas on where we can go with this:

1. I agree, we should ditch `Randomizable` as something like that should belong 
in a separate library or written by the user.

2. I also agree we should ditch the associated type on `RandomNumberGenerator`. 
I think we can sacrifice 32 bit generators using 64 bit ints to conform to the 
core team’s general use policy. This also makes default arguments for rngs 
possible which is a +1 for me!

I start to drift off from your design because `.random()` being an exception to 
ranges in that it’s inconsistent with other collection facilities and 
collection `.random()`. You make a few emails in the past that reference this 
as well. I think the right move is to have the static functions utilize the 
ranges to provide non optional types.

You wrote:

“
I see a couple points in favor of these static methods (or initializers) on the 
numeric types:

1) The collection method will need to return an optional to match the semantics 
of existing methods (like min()). If this is the only method available, every 
time someone needs a random value in the range 1...10, they’ll need to unwrap 
the result (with either force unwrapping, which people will complain about, or 
some kind of conditional binding, which is its own problem). Even if the 
semantics are the same (trapping on an empty range), the user experience of 
using a non-optional method will be better.



2) Floating-point ranges won’t get the collection method, so either we’ll have 
inconsistent APIs (random FP value is non-optional, random integer is optional) 
or we’ll make the FP API optional just to match. Both of those seem bad.
”

I believe this is the direction we need to go to keep consistency with 
collection based methods by justifying `.random(in:)` on the numeric types. 
With that in mind, Ben made a comment a long while ago saying, “The one 
downside is that you’d have to write 0..mailto:swift-evolution@swift.org>>, wrote:
I created a playground to explore this question, starting with a minimal subset 
of the proposal’s additions and building from there. The attached playground 
demonstrates what’s possible with this subset on the first page, then uses 
subsequent pages to explore how the main random facilities of the C++ STL work 
under this model. (In my opinion, they work pretty well!)

The subset in the playground has three main differences from the proposal:
 - It doesn't include a Randomizable protocol or a random property on numeric 
types.
 - It doesn't include the static random(in:) methods on numeric types, either.
 - The RandomNumberGenerator protocol doesn't have an associated type. Instead, 
it requires all conforming types to produce UInt64 values.

I’ve tried to include a bit of real-world usage in the playground to 
demonstrate what writing code would look like with these additions. Please take 
a look!

Nate


On Dec 2, 2017, at 9:50 PM, Dave Abrahams via swift-evolution 
<swift-evolution@swift.org<mailto:swift-evolution@swift.org>> wrote:

I don’t have much to say about this other than that I think the discussion 
seems way too narrow, focusing on spelling rather than on functionality and 
composability.  I consider the “generic random number library” design to be a 
mostly-solved problem, in the C++ standard library 
(http://en.cppreference.com/w/cpp/numeric/random).  Whatever goes into the 
Swift standard library does not need to have all those features right away, but 
should support being extended into something having the same general shape. IMO 
the right design strategy is to implement and use a Swift version of C++’s 
facilities and only then consider proposing [perhaps a subset of] that design 
for standardization in Swift.

Sent from my iPad

On Dec 2, 2017, at 5:12 PM, Kyle Murray via swift-evolution 
<swift-evolution@swift.org<mailto:swift-evolution@swift.org>> wrote:


On Dec 2, 2017, at 6:02 PM, Xiaodi Wu via swift-evolution 
<swift-evolution@swift.org<mailto:swift-evolution@swift.org>> wrote:

Instead, we ought to make clear to users both the features and the limitations 
of this API, to encourage use where suitable and to discourage use where 
unsuitable.

I like that you're considering the balance here. I've been lightly following 
this thread and want to add my thoughts on keeping crypto and pseudorandomness 
out of the name of at least one random API intended for general use.

For someone who doesn't know or care about

Re: [swift-evolution] [Proposal] Random Unification

2018-01-11 Thread Alejandro Alonso via swift-evolution
Sorry it takes me forever to respond! I finally got around to writing this! 
School really takes all my time x)

I have a few ideas on where we can go with this:

1. I agree, we should ditch `Randomizable` as something like that should belong 
in a separate library or written by the user.

2. I also agree we should ditch the associated type on `RandomNumberGenerator`. 
I think we can sacrifice 32 bit generators using 64 bit ints to conform to the 
core team’s general use policy. This also makes default arguments for rngs 
possible which is a +1 for me!

I start to drift off from your design because `.random()` being an exception to 
ranges in that it’s inconsistent with other collection facilities and 
collection `.random()`. You make a few emails in the past that reference this 
as well. I think the right move is to have the static functions utilize the 
ranges to provide non optional types.

You wrote:

“
I see a couple points in favor of these static methods (or initializers) on the 
numeric types:

1) The collection method will need to return an optional to match the semantics 
of existing methods (like min()). If this is the only method available, every 
time someone needs a random value in the range 1...10, they’ll need to unwrap 
the result (with either force unwrapping, which people will complain about, or 
some kind of conditional binding, which is its own problem). Even if the 
semantics are the same (trapping on an empty range), the user experience of 
using a non-optional method will be better.



2) Floating-point ranges won’t get the collection method, so either we’ll have 
inconsistent APIs (random FP value is non-optional, random integer is optional) 
or we’ll make the FP API optional just to match. Both of those seem bad.
”

I believe this is the direction we need to go to keep consistency with 
collection based methods by justifying `.random(in:)` on the numeric types. 
With that in mind, Ben made a comment a long while ago saying, “The one 
downside is that you’d have to write 0.., wrote:
I created a playground to explore this question, starting with a minimal subset 
of the proposal’s additions and building from there. The attached playground 
demonstrates what’s possible with this subset on the first page, then uses 
subsequent pages to explore how the main random facilities of the C++ STL work 
under this model. (In my opinion, they work pretty well!)

The subset in the playground has three main differences from the proposal:
 - It doesn't include a Randomizable protocol or a random property on numeric 
types.
 - It doesn't include the static random(in:) methods on numeric types, either.
 - The RandomNumberGenerator protocol doesn't have an associated type. Instead, 
it requires all conforming types to produce UInt64 values.

I’ve tried to include a bit of real-world usage in the playground to 
demonstrate what writing code would look like with these additions. Please take 
a look!

Nate


On Dec 2, 2017, at 9:50 PM, Dave Abrahams via swift-evolution 
> wrote:

I don’t have much to say about this other than that I think the discussion 
seems way too narrow, focusing on spelling rather than on functionality and 
composability.  I consider the “generic random number library” design to be a 
mostly-solved problem, in the C++ standard library 
(http://en.cppreference.com/w/cpp/numeric/random).  Whatever goes into the 
Swift standard library does not need to have all those features right away, but 
should support being extended into something having the same general shape. IMO 
the right design strategy is to implement and use a Swift version of C++’s 
facilities and only then consider proposing [perhaps a subset of] that design 
for standardization in Swift.

Sent from my iPad

On Dec 2, 2017, at 5:12 PM, Kyle Murray via swift-evolution 
> wrote:


On Dec 2, 2017, at 6:02 PM, Xiaodi Wu via swift-evolution 
> wrote:

Instead, we ought to make clear to users both the features and the limitations 
of this API, to encourage use where suitable and to discourage use where 
unsuitable.

I like that you're considering the balance here. I've been lightly following 
this thread and want to add my thoughts on keeping crypto and pseudorandomness 
out of the name of at least one random API intended for general use.

For someone who doesn't know or care about the subtleties of insecure or 
pseudorandom numbers, I'm not sure that the name insecureRandom is effectively 
much different than badRandom, at least in terms of the information it conveys 
to non-experts. To Greg's point, that's the opposite of the signal that the API 
name should suggest because it's what most people should use most of the time. 
As you say, this API is being designed for general use.

There's a cost to adding extra complexity to names, too. I don't 

Re: [swift-evolution] [Proposal] Random Unification

2018-01-11 Thread Alejandro Alonso via swift-evolution
If anything, Nate’s design is inconsistent as properties like `.first` and 
`.last` return an optional, and methods like `.min()` and `.max()` return an 
optional as well. Having `.random()` on ranges be an exception and return non 
optionals are inconsistent with other collection facilities, and with other 
collections that aren’t ranges that return optionals on `.random()`.

- Alejandro

On Jan 11, 2018, 12:06 PM -0600, Letanyan Arumugam via swift-evolution 
, wrote:
This is really cool and seems very powerful. However I don’t think we should 
sacrifice consistency for extendability. Especially when the extendability 
would not be what most people need.

What I am basically trying to say is that. I think the proposals current design 
direction fits better in a Random library rather than the Standard Library. And 
Nate’s design more directly addresses the motivating points of the proposal.

Letanyan


Sure. Small disclaimer that this was originally written back in the Swift 1~2 
days, so it is overdue for a simplifying rewrite.

Also, I should point out that the term “Source” has a special meaning in my 
code.  It basically means that something will provide an ~infinite collection 
of values of a type T.   I have what I call a “ConstantSource” which just wraps 
a T and gives it back when asked.  But then I have a bunch of other “sources" 
which let you create repeating patterns and do deferred calculations and things 
like that.  Finally I have a “RandomSource” which is part of what started this 
discussion.  You set up a RandomSource with a set of constraints, and then it 
gives you random values of T that adhere to those constraints (e.g. colors with 
a range of hues but the same saturation) whenever you ask for them.

This is really useful for doing things like graphic effects because, for 
example, I can ask for a source of colors and a source of line widths and then 
get out a large variety of interesting patterns from the same algorithm.  I can 
make simple stripes with ConstantSources, or I can make repeating patterns of 
lines with repeating sources, or I can have random colors which look good 
together by using a RandomSource.  I can take a BezierPath and make it look 
hand-drawn by breaking it into a bunch of lines and then offset the points a 
small amount using a RandomSource of CGVectors.

Not sure how useful this concept of randomness (and pattern) is to others, but 
I find it immensely useful!  Not sure of the best way to implement it.  The way 
I do it is a type erased protocol with private conforming structs and then 
public initializers on the type-erasing box.  The end result is that I can just 
say:

let myConst = Source(1) //ConstantSource with 1 as a value
let myPattern = Source([1, 2]) //OrderedSource which repeats 1, then 2 over and 
over forever
let myMeta = Source([myConst, myPattern]) //Will alternate between sub-sources 
in order. Can be nested.
//…and so on.

It is quite extensible and can make very complex/interesting patterns very 
easily.  What I like about it is that (well controlled) random values and 
patterns or constant values can be interchanged very easily.

The RandomSource has a RandomSourceCreatable Protocol that lets it take random 
bits and turn them into objects/structs of T adhering to the given constraints. 
 This is way more complex under the hood than it needs to be, but it works well 
in practice, and I haven’t gotten around to cleaning it up yet:

public protocol RandomSourceCreatable {
associatedtype ConstraintType = Self

///This should be implimented by simple types without internal components
static func createRandom(rnd value:RandomSourceValue, 
constraint:RandomSourceConstraint)->Self

///This should be implimented by complex types with multiple axis of constraints
static func createRandom(rnd value:RandomSourceValue, 
constraints:[String:RandomSourceConstraint])->Self

///Returns the proper dimension for the type given the constraints
static func dimension(given 
contraints:[String:RandomSourceConstraint])->RandomSourceDimension

///Validates the given contraints to make sure they can create valid 
objects. Only needs to be overridden for extremely complex types
static func validateConstraints(_ 
constraints:[String:RandomSourceConstraint])->Bool

///Convienience method which provides whitelist of keys for implicit 
validation of constraints
static var allowedConstraintKeys:Set {get}
   }

Most of these things also have default implementations so you only really have 
to deal with them for complex cases like colors or points.  The constraints are 
given using a dictionary with string keys and a RandomSourceConstraint value, 
which is defined like this:

public enum RandomSourceConstraint {
case none
case constant(T)
case min(T)
case max(T)
case range (T,T)
case custom ( (RandomSourceValue)->T )
//A bunch of boring convenience code here that transforms values 

Re: [swift-evolution] [Proposal] Random Unification

2018-01-08 Thread Alejandro Alonso via swift-evolution
I made changes last night that uses methods rather than properties if that’s 
all you’re worried about.

Sent from my iPhone

On Jan 8, 2018, at 15:27, David Hart via swift-evolution 
> wrote:

I much prefer the API from Nate Cook compared to the previous proposal. Its 
simpler, while still very powerful, and closer to Swift conventions (method 
instead of property).

On 8 Jan 2018, at 20:02, Nate Cook via swift-evolution 
> wrote:

I created a playground to explore this question, starting with a minimal subset 
of the proposal’s additions and building from there. The attached playground 
demonstrates what’s possible with this subset on the first page, then uses 
subsequent pages to explore how the main random facilities of the C++ STL work 
under this model. (In my opinion, they work pretty well!)

The subset in the playground has three main differences from the proposal:
 - It doesn't include a Randomizable protocol or a random property on numeric 
types.
 - It doesn't include the static random(in:) methods on numeric types, either.
 - The RandomNumberGenerator protocol doesn't have an associated type. Instead, 
it requires all conforming types to produce UInt64 values.

I’ve tried to include a bit of real-world usage in the playground to 
demonstrate what writing code would look like with these additions. Please take 
a look!

Nate



On Dec 2, 2017, at 9:50 PM, Dave Abrahams via swift-evolution 
> wrote:

I don’t have much to say about this other than that I think the discussion 
seems way too narrow, focusing on spelling rather than on functionality and 
composability.  I consider the “generic random number library” design to be a 
mostly-solved problem, in the C++ standard library 
(http://en.cppreference.com/w/cpp/numeric/random).  Whatever goes into the 
Swift standard library does not need to have all those features right away, but 
should support being extended into something having the same general shape. IMO 
the right design strategy is to implement and use a Swift version of C++’s 
facilities and only then consider proposing [perhaps a subset of] that design 
for standardization in Swift.

Sent from my iPad

On Dec 2, 2017, at 5:12 PM, Kyle Murray via swift-evolution 
> wrote:


On Dec 2, 2017, at 6:02 PM, Xiaodi Wu via swift-evolution 
> wrote:

Instead, we ought to make clear to users both the features and the limitations 
of this API, to encourage use where suitable and to discourage use where 
unsuitable.

I like that you're considering the balance here. I've been lightly following 
this thread and want to add my thoughts on keeping crypto and pseudorandomness 
out of the name of at least one random API intended for general use.

For someone who doesn't know or care about the subtleties of insecure or 
pseudorandom numbers, I'm not sure that the name insecureRandom is effectively 
much different than badRandom, at least in terms of the information it conveys 
to non-experts. To Greg's point, that's the opposite of the signal that the API 
name should suggest because it's what most people should use most of the time. 
As you say, this API is being designed for general use.

There's a cost to adding extra complexity to names, too. I don't think it's 
far-fetched to suspect that people who find insecureRandom in an autocomplete 
listing or search will think "Where's the plain random function?"... and then 
go looking for a community extension that will inevitably provide a trivial 
alias: func random() { return insecureRandom() }. That's the sort of adoption 
I'd expect from something for new programmers, like Swift Playgrounds. 
Someone's introduction to randomness in programming should probably involve no 
more than a straightforward mapping from the elementary definition, rather than 
forcing a teaching moment from more advanced math.

I think there are better places for caveat information than in the API names 
themselves; documentation being one clear destination. This is in contrast with 
Unsafe*Pointer, where the safety element is critical enough to be elevated to 
be more than caveat-level information. You can go really far and create really 
cool things before these caveats start to apply. Using randomness as a black 
box in an intro programming environment seems like a much more common scenario 
than someone attempting to roll their first crypto by only reading API names 
and hoping for the best.

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

Re: [swift-evolution] [Proposal] Random Unification

2018-01-02 Thread Alejandro Alonso via 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.

- 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


Re: [swift-evolution] [Proposal] Random Unification

2017-11-24 Thread Alejandro Alonso via swift-evolution
Regarding naming too many things “random”, I’ve talked to many developers on my 
end and they all don’t find it confusing. This proposal is aimed to make it 
obvious what the operation is doing when regarding random. I still agree that 
the proposed solution does just that and in practice feels good to write.

I disagree that sample is the correct naming to use here. Getting a sample is a 
verb in this context which would make it break API guidelines just as well as 
`pick()`. To sample is to “take a sample or samples of (something) for 
analysis.” I can agree to use `sampling()` which follows API guidelines. This 
would result in the following grammar for `[“hi”, “hello”, “hey”].sampling(2)`, 
“From array, get a sampling of 2"

- Alejandro


On Nov 23, 2017, 12:54 AM -0600, Xiaodi Wu , wrote:
On Wed, Nov 22, 2017 at 23:01 Alejandro Alonso 
> wrote:
Like I’ve said, python has different syntax grammar. We have to read each call 
site and form a sentence from it. `random.choice([1, 2, 3])` to me this reads, 
“Get a random choice from array”. This makes sense. Slapping the word choice as 
an instance property like `[1, 2, 3].choice` reads, “From array, get choice”. 
What is choice? This doesn’t make sense at all to me. To me, the only good 
solution is `[1, 2, 3].random` which reads, “From array, get random”. I 
actually think most users will be able to understand this at first glance 
rather than choice (or any or some).

Again, my concern here is that you are proposing to name multiple things 
"random". If this property should be called "random"--which I'm fine with--then 
the static method "random(in:)" should be named something else, and the static 
property "random" should be dropped altogether (as I advocate for reasons we 
just discussed) or renamed as well. It is simply too confusing that there are 
so many different "random" methods or properties. Meanwhile, isn't your default 
RNG also going to be called something like "DefaultRandom"?

In regards to the sample() function on collections, I have added this as I do 
believe this is something users need. The name I gave it was pick() as this 
reads, “From array, pick 2”.

The name "sample" has been used to good effect in other languages, has a well 
understood meaning in statistics, and is consistent with Swift language 
guidelines. The operation here is a sampling, and per Swift guidelines the name 
must be a noun: therefore, 'sample' is fitting. "Pick" does not intrinsically 
suggest randomness, whereas sample does, and your proposed reading uses it as a 
verb, whereas Swift guidelines tell us it must be a noun. I would advocate 
strongly for using well-established terminology and sticking with "sample."


On Nov 17, 2017, 8:32 PM -0600, Xiaodi Wu via swift-evolution 
>, wrote:
On Fri, Nov 17, 2017 at 7:11 PM, Brent Royal-Gordon 
> wrote:
On Nov 17, 2017, at 3:09 PM, Xiaodi Wu via swift-evolution 
> wrote:

But actually, Int.random followed by % is the much bigger issue and a very good 
cautionary tale for why T.random is not a good idea. Swift should help users do 
the correct thing, and getting a random value across the full domain and 
computing an integer modulus is never the correct thing to do because of modulo 
bias, yet it's a very common error to make. We are much better off eliminating 
this API and encouraging use of the correct API, thereby reducing the 
likelihood of users making this category of error.

Amen.

If (and I agree with this) the range-based notation is less intuitive 
(0..<10.random is certainly less discoverable than Int.random), then we ought 
to offer an API in the form of `Int.random(in:)` but not `Int.random`. This 
does not preclude a `Collection.random` API as Alejandro proposes, of course, 
and that has independent value as Gwendal says.

If we're not happy with the range syntax, maybe we should put 
`random(in:)`-style methods on the RNG protocol as extension methods instead. 
Then there's a nice, uniform style:

let diceRoll = rng.random(in: 1...6)
let card = rng.random(in: deck)
let isHeads = rng.random(in: [true, false])
let probability = rng.random(in: 0.0...1.0) // Special FloatingPoint overload

The only issue is that this makes the default RNG's name really important. 
Something like:

DefaultRandom.shared.random(in: 1...6)

Will be a bit of a pain for users.

I did in fact implement this style of RNG in NumericAnnex, but I'm not 
satisfied with the design myself. Not only is it a bit of an ergonomic thorn, 
there's also another drawback that actually has weighty implications:

Users aren't conditioned to reuse RNG instances. Perhaps, it is because it can 
"feel" wrong that multiple random instances should come from the *same* RNG. 
Instead, it "feels" more right to initialize a new 

Re: [swift-evolution] [Proposal] Random Unification

2017-11-22 Thread Alejandro Alonso via swift-evolution
Like I’ve said, python has different syntax grammar. We have to read each call 
site and form a sentence from it. `random.choice([1, 2, 3])` to me this reads, 
“Get a random choice from array”. This makes sense. Slapping the word choice as 
an instance property like `[1, 2, 3].choice` reads, “From array, get choice”. 
What is choice? This doesn’t make sense at all to me. To me, the only good 
solution is `[1, 2, 3].random` which reads, “From array, get random”. I 
actually think most users will be able to understand this at first glance 
rather than choice (or any or some). In regards to the sample() function on 
collections, I have added this as I do believe this is something users need. 
The name I gave it was pick() as this reads, “From array, pick 2”.

- Alejandro

On Nov 17, 2017, 8:32 PM -0600, Xiaodi Wu via swift-evolution 
, wrote:
On Fri, Nov 17, 2017 at 7:11 PM, Brent Royal-Gordon 
> wrote:
On Nov 17, 2017, at 3:09 PM, Xiaodi Wu via swift-evolution 
> wrote:

But actually, Int.random followed by % is the much bigger issue and a very good 
cautionary tale for why T.random is not a good idea. Swift should help users do 
the correct thing, and getting a random value across the full domain and 
computing an integer modulus is never the correct thing to do because of modulo 
bias, yet it's a very common error to make. We are much better off eliminating 
this API and encouraging use of the correct API, thereby reducing the 
likelihood of users making this category of error.

Amen.

If (and I agree with this) the range-based notation is less intuitive 
(0..<10.random is certainly less discoverable than Int.random), then we ought 
to offer an API in the form of `Int.random(in:)` but not `Int.random`. This 
does not preclude a `Collection.random` API as Alejandro proposes, of course, 
and that has independent value as Gwendal says.

If we're not happy with the range syntax, maybe we should put 
`random(in:)`-style methods on the RNG protocol as extension methods instead. 
Then there's a nice, uniform style:

let diceRoll = rng.random(in: 1...6)
let card = rng.random(in: deck)
let isHeads = rng.random(in: [true, false])
let probability = rng.random(in: 0.0...1.0) // Special FloatingPoint overload

The only issue is that this makes the default RNG's name really important. 
Something like:

DefaultRandom.shared.random(in: 1...6)

Will be a bit of a pain for users.

I did in fact implement this style of RNG in NumericAnnex, but I'm not 
satisfied with the design myself. Not only is it a bit of an ergonomic thorn, 
there's also another drawback that actually has weighty implications:

Users aren't conditioned to reuse RNG instances. Perhaps, it is because it can 
"feel" wrong that multiple random instances should come from the *same* RNG. 
Instead, it "feels" more right to initialize a new RNG for every random number. 
After all, if one RNG is random, two must be randomer! This error is seen with 
some frequency in other languages that adopt this design, and they sometimes 
resort to educating users through documentation that isn't consistently heeded.

Of course, you and I both know that this is not ideal for performance. 
Moreover, for a number of PRNG algorithms, the first few hundred or thousand 
iterations can be more predictable than later iterations. (Some algorithms 
discard the first n iterations, but whether that's adequate depends on the 
quality of the seed, IIUC.) Both of these issues don't apply specifically to a 
default RNG type that cannot be initialized and always uses entropy from the 
global pool, but that's not enough to vindicate the design, IMO. By emphasizing 
*which* RNG instance is being used for random number generation, the design 
encourages non-reuse of non-default RNGs, which is precisely where this common 
error matters for performance (and maybe security).

Maybe we call the default RNG instance `random`, and then give the 
`random(in:)` methods another name, like `choose(in:)`?

let diceRoll = random.choose(in: 1...6)
let card = random.choose(in: deck)
let isHeads = random.choose(in: [true, false])
let probability = random.choose(in: 0.0...1.0)
let diceRoll = rng.choose(in: 1...6)
let card = rng.choose(in: deck)
let isHeads = rng.choose(in: [true, false])
let probability = rng.choose(in: 0.0...1.0)

This would allow us to keep the default RNG's type private and expose it only 
as an existential—which means more code will treat RNGs as black boxes, and 
people will extend the RNG protocol instead of the default RNG struct—while 
also putting our default random number generator under the name `random`, which 
is probably where people will look for such a thing.

I've said this already in my feedback, but it can get lost in the long chain of 
replies, so I'll repeat myself here because it's relevant to the discussion. I 
think one of the 

Re: [swift-evolution] [Proposal] Random Unification

2017-11-22 Thread Alejandro Alonso via swift-evolution
I pushed some updates to the proposal with a reflected API, but I do not agree 
that we should rid the API of T.random just because some users will misuse it. 
I think the correct solution here is to include T.random(in:) (which does not 
return an optional making it not a second typing of (min ... max).random). Like 
Jonathon said, autocomplete will display both of these and users will be able 
to select random(in:). I also disagree that T.random is _always_ followed by 
modulo because if we look at arc4random() it’s range is the whole domain of 
UInt32. Users don’t put a modulo here because they know the correct way to do 
it is through arc4random_uniform(), either through online tutorials, or by 
reading documentation. If we did get rid of T.random, users who want a random 
byte for instance would have to write UInt8.random(in: 0 … 255) every time. 
Developers will make wrappers over this. I believe the correct solution is to 
keep T.random for those who won’t misuse it and T.random(in:) for those who 
need to a random value within a range.

- Alejandro

On Nov 17, 2017, 5:09 PM -0600, Xiaodi Wu <xiaodi...@gmail.com>, wrote:
On Fri, Nov 17, 2017 at 10:10 AM, Gwendal Roué via swift-evolution 
<swift-evolution@swift.org<mailto:swift-evolution@swift.org>> wrote:

> Le 17 nov. 2017 à 16:04, Alejandro Alonso via swift-evolution 
> <swift-evolution@swift.org<mailto:swift-evolution@swift.org>> a écrit :
>
> If we go back to your example, you never call FixedWidthInteger.random 
> either, you call range.random. Does this mean integer types shouldn’t have 
> .random? No, because it means get a random number from it’s internal range 
> (alias to (min ... max).random). I think we can all agree that Integer.random 
> is a nicer api than making a range of its bounds. The same goes for 
> Date.random and Color.random.
>
> - Alejandro

Hello,

I'm not random expert, but it has never happened in my developer life (backend 
& frontend app developer) that I have used a pure random value from the full 
domain of the random type. In this life:

- Int.random is _always_ followed by % modulo. Unless the better 
arc4random_uniform(max) is used.
- Color.random is _never_ used, because random colors look bad.
- Date.random is _never_ used, because time is a physical unit, and random 
points in time do not match any physical use case.

This does not mean that random values from the full domain are useless. Of 
course not: math apps, fuzzers, etc. need them.

Yet a range-based API would be much welcomed by regular app developers. And 
also Array.randomElement(), Array.shuffled(), etc, because there are plenty 
naive and bad algorithms for those simple tasks.

Certainly it's hard to defend Date.random (and yes, it might be useful for a 
fuzzer, but that's a very niche use case--and in that case the fuzzer should 
probably also generate invalid/non-existent dates, which surely Date.random 
should not do). But actually, Int.random followed by % is the much bigger issue 
and a very good cautionary tale for why T.random is not a good idea. Swift 
should help users do the correct thing, and getting a random value across the 
full domain and computing an integer modulus is never the correct thing to do 
because of modulo bias, yet it's a very common error to make. We are much 
better off eliminating this API and encouraging use of the correct API, thereby 
reducing the likelihood of users making this category of error.

If (and I agree with this) the range-based notation is less intuitive 
(0..<10.random is certainly less discoverable than Int.random), then we ought 
to offer an API in the form of `Int.random(in:)` but not `Int.random`. This 
does not preclude a `Collection.random` API as Alejandro proposes, of course, 
and that has independent value as Gwendal says.

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


Re: [swift-evolution] [Proposal] Random Unification

2017-11-17 Thread Alejandro Alonso via swift-evolution
I agree with all your points, but that’s if we were implementing a randomness 
source. What we’re providing is a random number generator that takes some 
randomness from a source and uses that to give the user an actual number it 
knows about. That differs from a randomness source because a generator doesn’t 
create randomness, it simply uses it to generate a random number. For this 
reason I think that rngs should not write to a pointer.

- Alejandro

El nov. 17, 2017, a la(s) 11:29, David Waite 
<da...@alkaline-solutions.com<mailto:da...@alkaline-solutions.com>> escribió:


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

While this could work, I don’t believe this aligns with Swift. 
SecRandomCopyBytes and arc4random_buf do it this way because of the languages 
they were built in, and for SecRandomCopyBytes, it needs to also return an 
error (in the form of its return value). For custom generators this doesn’t 
make sense to me because it seems as if each generator will have the same code 
to return an integer of a different size from what it’ll be producing. I really 
like Xiaodi’s solution to explicitly state what type of integer a custom 
generator will return, and as a default implementation, we provide a way to 
transform that.

- Alejandro


The random source does not know about integers or floats or colors. It just 
provides randomness. Higher level code is what determines for instance how to 
generate (for example) a random number between 1 and 27 with equal probability 
- which could theoretically require more than a 64 bits of randomness (with 
probability of that depending on luck and the algorithm used)

A double is not a uniform distribution, so likewise simply casting a 64 bit 
integer value to a double would not yield appropriate results (you’d have a 
significant chance of NaN values, for instance)

Thats why I would recommend having the random source just be a sequence of 
bytes. The higher level API choosing random elements from a Strideable or 
shuffling an array *should* be the interfaces that developers use, rather than 
directly reading from the random source

I proposed “read” below because it is compatible with the signature on 
InputStream, which both would allow you to easily bridge /dev/random or 
/dev/urandom in as well as have predefined data as a source of randomness for 
predictable testing.

Predictable randomness and multiple sources of randomness are important in a 
few scenarios, including gaming where the same “random” choices need to be made 
locally for each player to keep the games in sync.

-DW



On Nov 15, 2017, 11:26 AM -0600, Nate Cook 
<natec...@apple.com<mailto:natec...@apple.com>>, wrote:
On Nov 13, 2017, at 7:38 PM, Xiaodi Wu 
<xiaodi...@gmail.com<mailto:xiaodi...@gmail.com>> wrote:

On Mon, Nov 13, 2017 at 7:12 PM, Alejandro Alonso 
<aalonso...@outlook.com<mailto:aalonso...@outlook.com>> wrote:
After thinking about this for a while, I don’t agree with with an associated 
type on RandomNumberGenerator. I think a generic FixedWidthInteger & 
UnsignedInteger should be sufficient. If there were an associated type, and the 
default for Random was UInt32, then there might be some arguments about 
allowing Double to utilize the full 64 bit precision. We could make Random32 
and Random64, but I think people will ask why there isn’t a Random8 or Random16 
for those bit widths. The same could also be said that any experienced 
developer would know that his PRNG would be switched if he asked for 32 bit or 
64 bit.

I don't understand. Of course, Double would require 64 bits of randomness. It 
would obtain this by calling `next()` as many times as necessary to obtain the 
requisite number of bits.

At base, any PRNG algorithm yields some fixed number of bits on each iteration. 
You can certainly have a function that returns an arbitrary number of random 
bits (in fact, I would recommend that such an algorithm be a protocol extension 
method on RandomNumberGenerator), but it must be built on top of a function 
that returns a fixed number of bits, where that number is determined on a 
per-algorithm basis. Moreover--and this is important--generating a random 
unsigned integer of arbitrary bit width in a sound way is actually subtly 
_different_ from generating a floating-point value of a certain bit width, and 
I'm not sure that one can be built on top of the other. Compare, for example:

https://github.com/xwu/NumericAnnex/blob/c962760bf974a84ec57d8c5e94c91f06584e2453/Sources/PRNG.swift#L157
https://github.com/xwu/NumericAnnex/blob/c962760bf974a84ec57d8c5e94c91f06584e2453/Sources/PRNG.swift#L316

(These are essentially Swift versions of C++ algorithms.)

Basically, what I'm saying is that RandomNumberGenerator needs a `next()` 
method that returns a fixed number of bits, and extension methods that build on 
that to

Re: [swift-evolution] [Proposal] Random Unification

2017-11-17 Thread Alejandro Alonso via swift-evolution
I can think of many cases where you actually need a random color, not because 
it doesn’t look good, but because you need a color you don’t have. 

The proposed solution most definitely includes a range based random api for 
those who don’t need the full domain (0 ..< 10).random. What I’m trying to 
express is that some people need the full domain (Type.random) and some need 
the range based api ((min ..< max).random) (or ...). The proposed solution 
covers both of these and provides solutions to each.

- Alejandro

El nov. 17, 2017, a la(s) 10:10, Gwendal Roué <gwendal.r...@gmail.com> escribió:

> 
>> Le 17 nov. 2017 à 16:04, Alejandro Alonso via swift-evolution 
>> <swift-evolution@swift.org> a écrit :
>> 
>> If we go back to your example, you never call FixedWidthInteger.random 
>> either, you call range.random. Does this mean integer types shouldn’t have 
>> .random? No, because it means get a random number from it’s internal range 
>> (alias to (min ... max).random). I think we can all agree that 
>> Integer.random is a nicer api than making a range of its bounds. The same 
>> goes for Date.random and Color.random.
>> 
>> - Alejandro
> 
> Hello,
> 
> I'm not random expert, but it has never happened in my developer life 
> (backend & frontend app developer) that I have used a pure random value from 
> the full domain of the random type. In this life:
> 
> - Int.random is _always_ followed by % modulo. Unless the better 
> arc4random_uniform(max) is used.
> - Color.random is _never_ used, because random colors look bad.
> - Date.random is _never_ used, because time is a physical unit, and random 
> points in time do not match any physical use case.
> 
> This does not mean that random values from the full domain are useless. Of 
> course not: math apps, fuzzers, etc. need them.
> 
> Yet a range-based API would be much welcomed by regular app developers. And 
> also Array.randomElement(), Array.shuffled(), etc, because there are plenty 
> naive and bad algorithms for those simple tasks.
> 
> Gwendal Roué
> 
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Random Unification

2017-11-17 Thread Alejandro Alonso via swift-evolution
ndom would return a non-optional, and Array(0 ..< 10).random 
would return an optional. I can agree that something like (0 ..< 10).random is 
hard to discover, so I added Int.random(in: 0 ..< 10) (along with 
BinaryFloatingPoint). However, these are not requirements of Randomizable. I 
think these methods would benefit more if they were extension methods:

extension Randomizable where Self: FixedWidthInteger, Self.Stride: 
SignedInteger {
 public static func random(
  in range: Countable{Closed}Range,
  using generator: RandomNumberGenerator
 ) -> Self {
  return range.random(using: generator)
 }
}

extension Randomizable where Self: BinaryFloatingPointer {
 public static func random(
  in range: {Closed}Range,
  using generator: RandomNumberGenerator
 ) -> Self {
  return range.random
 }
}

I think external types that wish to do something similar, like 
Data.random(bytes: 128), could extend Randomizable with their own custom needs. 
The stdlib would at this point provide all the features needed to make this 
happen very simply for something like Data.random(bytes: 128).

- Alejandro

On Nov 5, 2017, 10:44 PM -0600, Nate Cook 
<natec...@apple.com<mailto:natec...@apple.com>>, wrote:
Thanks for continuing to push this forward, Alejandro! I’m excited about the 
potential of having access to these APIs as part of the standard library. Here 
are a few comments on some different parts of the proposal:

1) For your RandomGenerator protocol, I’m not totally clear on the semantics of 
the next(_:) and next(_:upperBound:) methods. Do they both have zero as their 
lower bound, for example? I’m not sure it makes sense to have signed integers 
generated directly by an RNG—perhaps T: FixedWidthInteger & UnsignedInteger 
would be a more useful constraint. (Does it even need to be generic? What if 
RNGs just generate UInt32s?)

2) Can you say more about the purpose of the Randomizable protocol? How would 
we use that protocol in useful ways that we wouldn’t get from being able to 
select random values from ranges (half-open and closed) of FixedWidthInteger / 
BinaryFloatingPoint? My experience has been that a full-width random value is 
rarely what a user needs.

3) I agree with Xiaodi that Random should probably be a struct with a single 
shared instance, but I don’t think it should be internal. Hiding that shared 
RNG would make it hard for non-stdlib additions to have the same usage, as they 
would need to have completely separate implementations for the “default” and 
custom RNG versions.

4) I would also still suggest that the simplest version of random (that you use 
to get a value from a range or an element from a collection) should be a 
function, not a property. Collection properties like first, last, and count all 
represent facts that already exist about a collection, and don’t change unless 
the collection itself changes. Choosing a random element, on the other hand, is 
clearly going to be freshly performed on each call. In addition, with the 
notable exception of count, we try to ensure O(1) performance for properties, 
while random will be O(n) except in random-access collections. Finally, if it 
is a method, we can unify the two versions by providing a single method with 
the shared RNG as the default parameter.

5) To match the sorted() method, shuffled() should be on Sequence instead of 
Collection. I don’t think either shuffled() or shuffle() needs to be a protocol 
requirement, since there isn’t really any kind of customization necessary for 
different kinds of collections. Like the sorting algorithms, both could be 
regular extension methods.

6) I don’t know whether or not a consensus has formed around the correct 
spelling of the APIs for generating random values. From the proposal it looks 
like the preferred ways of getting a random value in a range would be to use 
the random property (or method) on a range or closed range:

(0..<10).random  // 7
(0.0 ... 5.0).random // 4.112312

If that’s the goal, and we don’t want those values to be optional, we’ll need 
an implementation of random for floating-point ranges and an overload for 
fixed-width integer ranges. That said, I don’t think that style is as 
discoverable as having static methods or initializers available on the 
different types:

Int.random(in: 0..<10)
Double.random(in: 0.0 ... 5.0)
// or maybe
Int(randomIn: 0..<10)
Double(randomIn: 0.0 ... 5.0)

(My only quibble with the initializer approach is that Bool would be awkward.)

In addition, this alternative approach could make creating random values more 
consistent with types that don’t work well in ranges:

Data.random(bytes: 128)
Color.random(r: 0...0, g: 0...1, b: 0...1, a: 1...1)



Thanks again!
Nate

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

https://github.com/apple/swift-evolution/pul

Re: [swift-evolution] [Proposal] Random Unification

2017-11-16 Thread Alejandro Alonso via swift-evolution
While this could work, I don’t believe this aligns with Swift. 
SecRandomCopyBytes and arc4random_buf do it this way because of the languages 
they were built in, and for SecRandomCopyBytes, it needs to also return an 
error (in the form of its return value). For custom generators this doesn’t 
make sense to me because it seems as if each generator will have the same code 
to return an integer of a different size from what it’ll be producing. I really 
like Xiaodi’s solution to explicitly state what type of integer a custom 
generator will return, and as a default implementation, we provide a way to 
transform that.

- Alejandro

On Nov 15, 2017, 11:26 AM -0600, Nate Cook , wrote:
On Nov 13, 2017, at 7:38 PM, Xiaodi Wu 
> wrote:

On Mon, Nov 13, 2017 at 7:12 PM, Alejandro Alonso 
> wrote:
After thinking about this for a while, I don’t agree with with an associated 
type on RandomNumberGenerator. I think a generic FixedWidthInteger & 
UnsignedInteger should be sufficient. If there were an associated type, and the 
default for Random was UInt32, then there might be some arguments about 
allowing Double to utilize the full 64 bit precision. We could make Random32 
and Random64, but I think people will ask why there isn’t a Random8 or Random16 
for those bit widths. The same could also be said that any experienced 
developer would know that his PRNG would be switched if he asked for 32 bit or 
64 bit.

I don't understand. Of course, Double would require 64 bits of randomness. It 
would obtain this by calling `next()` as many times as necessary to obtain the 
requisite number of bits.

At base, any PRNG algorithm yields some fixed number of bits on each iteration. 
You can certainly have a function that returns an arbitrary number of random 
bits (in fact, I would recommend that such an algorithm be a protocol extension 
method on RandomNumberGenerator), but it must be built on top of a function 
that returns a fixed number of bits, where that number is determined on a 
per-algorithm basis. Moreover--and this is important--generating a random 
unsigned integer of arbitrary bit width in a sound way is actually subtly 
_different_ from generating a floating-point value of a certain bit width, and 
I'm not sure that one can be built on top of the other. Compare, for example:

https://github.com/xwu/NumericAnnex/blob/c962760bf974a84ec57d8c5e94c91f06584e2453/Sources/PRNG.swift#L157
https://github.com/xwu/NumericAnnex/blob/c962760bf974a84ec57d8c5e94c91f06584e2453/Sources/PRNG.swift#L316

(These are essentially Swift versions of C++ algorithms.)

Basically, what I'm saying is that RandomNumberGenerator needs a `next()` 
method that returns a fixed number of bits, and extension methods that build on 
that to return T : FixedWidthInteger & UnsignedInteger of arbitrary bit width 
or U : BinaryFloatingPoint of an arbitrary number of bits of precision. Each 
individual RNG does not need to reimplement the latter methods, just a method 
to return a `next()` value of a fixed number of bits. You are welcome to use my 
implementation.

An alternative to this is to have the random generator write a specified number 
of bytes to a pointer’s memory, as David Waite and others have suggested. This 
is same way arc4random_buf and SecRandomCopyBytes are implemented. Each random 
number generator could then choose the most efficient way to provide the 
requested number of bytes. The protocol could look something like this:

protocol RandomNumberGenerator {
/// Writes the specified number of bytes to the given pointer’s memory.
func read(into p: UnsafeMutableRawPointer, bytes: Int)
}

This is less user-friendly than having a next() method, but I think that’s a 
good thing—we very much want people who need a random value to use higher-level 
APIs and just pass the RNG as a parameter when necessary.

Nate


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


Re: [swift-evolution] [Proposal] Random Unification

2017-11-13 Thread Alejandro Alonso via swift-evolution
 a more useful constraint. (Does it even need to be generic? What if 
RNGs just generate UInt32s?)

2) Can you say more about the purpose of the Randomizable protocol? How would 
we use that protocol in useful ways that we wouldn’t get from being able to 
select random values from ranges (half-open and closed) of FixedWidthInteger / 
BinaryFloatingPoint? My experience has been that a full-width random value is 
rarely what a user needs.

3) I agree with Xiaodi that Random should probably be a struct with a single 
shared instance, but I don’t think it should be internal. Hiding that shared 
RNG would make it hard for non-stdlib additions to have the same usage, as they 
would need to have completely separate implementations for the “default” and 
custom RNG versions.

4) I would also still suggest that the simplest version of random (that you use 
to get a value from a range or an element from a collection) should be a 
function, not a property. Collection properties like first, last, and count all 
represent facts that already exist about a collection, and don’t change unless 
the collection itself changes. Choosing a random element, on the other hand, is 
clearly going to be freshly performed on each call. In addition, with the 
notable exception of count, we try to ensure O(1) performance for properties, 
while random will be O(n) except in random-access collections. Finally, if it 
is a method, we can unify the two versions by providing a single method with 
the shared RNG as the default parameter.

5) To match the sorted() method, shuffled() should be on Sequence instead of 
Collection. I don’t think either shuffled() or shuffle() needs to be a protocol 
requirement, since there isn’t really any kind of customization necessary for 
different kinds of collections. Like the sorting algorithms, both could be 
regular extension methods.

6) I don’t know whether or not a consensus has formed around the correct 
spelling of the APIs for generating random values. From the proposal it looks 
like the preferred ways of getting a random value in a range would be to use 
the random property (or method) on a range or closed range:

(0..<10).random  // 7
(0.0 ... 5.0).random // 4.112312

If that’s the goal, and we don’t want those values to be optional, we’ll need 
an implementation of random for floating-point ranges and an overload for 
fixed-width integer ranges. That said, I don’t think that style is as 
discoverable as having static methods or initializers available on the 
different types:

Int.random(in: 0..<10)
Double.random(in: 0.0 ... 5.0)
// or maybe
Int(randomIn: 0..<10)
Double(randomIn: 0.0 ... 5.0)

(My only quibble with the initializer approach is that Bool would be awkward.)

In addition, this alternative approach could make creating random values more 
consistent with types that don’t work well in ranges:

Data.random(bytes: 128)
Color.random(r: 0...0, g: 0...1, b: 0...1, a: 1...1)

————

Thanks again!
Nate

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

https://github.com/apple/swift-evolution/pull/760 is the current API and 
proposed solution.

- Alejandro

On Nov 5, 2017, 6:18 PM -0600, Xiaodi Wu 
<xiaodi...@gmail.com<mailto:xiaodi...@gmail.com>>, wrote:
My comments are directed to the "more up-to-date" document that you just linked 
to in your reply to Jon. Is that one outdated? If so, can you send a link to 
the updated proposal and implementation for which you're soliciting feedback?


On Sun, Nov 5, 2017 at 6:12 PM, Alejandro Alonso 
<aalonso...@outlook.com<mailto:aalonso...@outlook.com>> wrote:
The proposal and implementation have the current updated API. The link I sent 
Jon was the one I brought up a few weeks ago which is outdated now. The 
proposal answers all of your questions. As for `.random` being a function, some 
would argue that it behaves in the same way as `.first` and `.last` which are 
properties.

- Alejandro

On Nov 5, 2017, 6:07 PM -0600, Xiaodi Wu 
<xiaodi...@gmail.com<mailto:xiaodi...@gmail.com>>, wrote:
A few quick thoughts:

I know that there's been some discussion that `(1...10).random` is the best 
spelling, but I'd like to push back on that suggestion. When I want a random 
number, I tend to think of the type I want first ("I want a random integer") 
and then a range ("I want a random integer between a and b"), not the other way 
around. My intuition is that `Int.random(in:)` will be more discoverable, both 
on that basis and because it is more similar to other languages' syntax 
(`Math.random` in JavaScript and `randint` in NumPy,
for example). It also has the advantage that the type is explicit, which I 
think is particularly useful in this case because the value itself is, well, 
random.

I would also argue that, `random` is most appropriately a me

Re: [swift-evolution] [Proposal] Random Unification

2017-11-12 Thread Alejandro Alonso via swift-evolution
le to 
select random values from ranges (half-open and closed) of FixedWidthInteger / 
BinaryFloatingPoint? My experience has been that a full-width random value is 
rarely what a user needs.

3) I agree with Xiaodi that Random should probably be a struct with a single 
shared instance, but I don’t think it should be internal. Hiding that shared 
RNG would make it hard for non-stdlib additions to have the same usage, as they 
would need to have completely separate implementations for the “default” and 
custom RNG versions.

4) I would also still suggest that the simplest version of random (that you use 
to get a value from a range or an element from a collection) should be a 
function, not a property. Collection properties like first, last, and count all 
represent facts that already exist about a collection, and don’t change unless 
the collection itself changes. Choosing a random element, on the other hand, is 
clearly going to be freshly performed on each call. In addition, with the 
notable exception of count, we try to ensure O(1) performance for properties, 
while random will be O(n) except in random-access collections. Finally, if it 
is a method, we can unify the two versions by providing a single method with 
the shared RNG as the default parameter.

5) To match the sorted() method, shuffled() should be on Sequence instead of 
Collection. I don’t think either shuffled() or shuffle() needs to be a protocol 
requirement, since there isn’t really any kind of customization necessary for 
different kinds of collections. Like the sorting algorithms, both could be 
regular extension methods.

6) I don’t know whether or not a consensus has formed around the correct 
spelling of the APIs for generating random values. From the proposal it looks 
like the preferred ways of getting a random value in a range would be to use 
the random property (or method) on a range or closed range:

(0..<10).random  // 7
(0.0 ... 5.0).random // 4.112312

If that’s the goal, and we don’t want those values to be optional, we’ll need 
an implementation of random for floating-point ranges and an overload for 
fixed-width integer ranges. That said, I don’t think that style is as 
discoverable as having static methods or initializers available on the 
different types:

Int.random(in: 0..<10)
Double.random(in: 0.0 ... 5.0)
// or maybe
Int(randomIn: 0..<10)
Double(randomIn: 0.0 ... 5.0)

(My only quibble with the initializer approach is that Bool would be awkward.)

In addition, this alternative approach could make creating random values more 
consistent with types that don’t work well in ranges:

Data.random(bytes: 128)
Color.random(r: 0...0, g: 0...1, b: 0...1, a: 1...1)

————

Thanks again!
Nate

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

https://github.com/apple/swift-evolution/pull/760 is the current API and 
proposed solution.

- Alejandro

On Nov 5, 2017, 6:18 PM -0600, Xiaodi Wu 
<xiaodi...@gmail.com<mailto:xiaodi...@gmail.com>>, wrote:
My comments are directed to the "more up-to-date" document that you just linked 
to in your reply to Jon. Is that one outdated? If so, can you send a link to 
the updated proposal and implementation for which you're soliciting feedback?


On Sun, Nov 5, 2017 at 6:12 PM, Alejandro Alonso 
<aalonso...@outlook.com<mailto:aalonso...@outlook.com>> wrote:
The proposal and implementation have the current updated API. The link I sent 
Jon was the one I brought up a few weeks ago which is outdated now. The 
proposal answers all of your questions. As for `.random` being a function, some 
would argue that it behaves in the same way as `.first` and `.last` which are 
properties.

- Alejandro

On Nov 5, 2017, 6:07 PM -0600, Xiaodi Wu 
<xiaodi...@gmail.com<mailto:xiaodi...@gmail.com>>, wrote:
A few quick thoughts:

I know that there's been some discussion that `(1...10).random` is the best 
spelling, but I'd like to push back on that suggestion. When I want a random 
number, I tend to think of the type I want first ("I want a random integer") 
and then a range ("I want a random integer between a and b"), not the other way 
around. My intuition is that `Int.random(in:)` will be more discoverable, both 
on that basis and because it is more similar to other languages' syntax 
(`Math.random` in JavaScript and `randint` in NumPy,
for example). It also has the advantage that the type is explicit, which I 
think is particularly useful in this case because the value itself is, well, 
random.

I would also argue that, `random` is most appropriately a method and not a 
property; there's no hard and fast rule for this, but the fact that the result 
is stochastic suggests (to me) that it's not a "property" of the range (or, for 
that matter, of the type).

I would reiterate here my qualms a

Re: [swift-evolution] [Proposal] Random Unification

2017-11-12 Thread Alejandro Alonso via swift-evolution
 necessary for 
different kinds of collections. Like the sorting algorithms, both could be 
regular extension methods.

6) I don’t know whether or not a consensus has formed around the correct 
spelling of the APIs for generating random values. From the proposal it looks 
like the preferred ways of getting a random value in a range would be to use 
the random property (or method) on a range or closed range:

(0..<10).random  // 7
(0.0 ... 5.0).random // 4.112312

If that’s the goal, and we don’t want those values to be optional, we’ll need 
an implementation of random for floating-point ranges and an overload for 
fixed-width integer ranges. That said, I don’t think that style is as 
discoverable as having static methods or initializers available on the 
different types:

Int.random(in: 0..<10)
Double.random(in: 0.0 ... 5.0)
// or maybe
Int(randomIn: 0..<10)
Double(randomIn: 0.0 ... 5.0)

(My only quibble with the initializer approach is that Bool would be awkward.)

In addition, this alternative approach could make creating random values more 
consistent with types that don’t work well in ranges:

Data.random(bytes: 128)
Color.random(r: 0...0, g: 0...1, b: 0...1, a: 1...1)



Thanks again!
Nate

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

https://github.com/apple/swift-evolution/pull/760 is the current API and 
proposed solution.

- Alejandro

On Nov 5, 2017, 6:18 PM -0600, Xiaodi Wu 
<xiaodi...@gmail.com<mailto:xiaodi...@gmail.com>>, wrote:
My comments are directed to the "more up-to-date" document that you just linked 
to in your reply to Jon. Is that one outdated? If so, can you send a link to 
the updated proposal and implementation for which you're soliciting feedback?


On Sun, Nov 5, 2017 at 6:12 PM, Alejandro Alonso 
<aalonso...@outlook.com<mailto:aalonso...@outlook.com>> wrote:
The proposal and implementation have the current updated API. The link I sent 
Jon was the one I brought up a few weeks ago which is outdated now. The 
proposal answers all of your questions. As for `.random` being a function, some 
would argue that it behaves in the same way as `.first` and `.last` which are 
properties.

- Alejandro

On Nov 5, 2017, 6:07 PM -0600, Xiaodi Wu 
<xiaodi...@gmail.com<mailto:xiaodi...@gmail.com>>, wrote:
A few quick thoughts:

I know that there's been some discussion that `(1...10).random` is the best 
spelling, but I'd like to push back on that suggestion. When I want a random 
number, I tend to think of the type I want first ("I want a random integer") 
and then a range ("I want a random integer between a and b"), not the other way 
around. My intuition is that `Int.random(in:)` will be more discoverable, both 
on that basis and because it is more similar to other languages' syntax 
(`Math.random` in JavaScript and `randint` in NumPy,
for example). It also has the advantage that the type is explicit, which I 
think is particularly useful in this case because the value itself is, well, 
random.

I would also argue that, `random` is most appropriately a method and not a 
property; there's no hard and fast rule for this, but the fact that the result 
is stochastic suggests (to me) that it's not a "property" of the range (or, for 
that matter, of the type).

I would reiterate here my qualms about `Source` being the term used for a 
generator. These types are not a _source_ of entropy but rather a _consumer_ of 
entropy.

`UnsafeRandomSource` needs to be renamed; "unsafe" has a specific meaning in 
Swift--that is, memory safety, and this is not it. Moreover, it's questionable 
whether this protocol is useful in any sense. What useful generic algorithms 
can one write with such a protocol?

`XoroshiroRandom` cannot be seeded by any `Numeric` value; depending on the 
specific algorithm it needs a seed of a specific bit width. If you default the 
shared instance to being seeded with an `Int` then you will have to have 
distinct implementations for 32-bit and 64-bit platforms. This is unadvisable. 
On that note, your `UnsafeRandomSource` needs to have an associated type and 
not a generic `` for the seed.

The default random number generator should be cryptographically secure; 
however, it's not clear to me that it should be device random.

I agree with others that alternative random number generators other than the 
default RNG (and, if not default, possibly also the device RNG) should be 
accommodated by the protocol hierarchy but not necessarily supplied in the 
stdlib.

The term `Randomizable` means something specific which is not how it's used in 
your proposed protocol.

There's still the open question, not answered, about how requesting an instance 
of the hardware RNG behaves when there's insufficient or no entropy. Does it 
return nil, throw, trap, or 

Re: [swift-evolution] [Proposal] Random Unification

2017-11-05 Thread Alejandro Alonso via swift-evolution
ou a random Float; or it may trap
```

With that, it also becomes clear why--and I agree with you--an independent 
`Int.random(in: 0..<5)` is not necessary. `(0..<5).choice` is fine, and it can 
now appropriately return a value of type `T?` because it no longer needs to 
parallel `Int.random`.

* * *

More in the bikeshedding arena, I take issue with some of the names:

- I reiterate my comment that `Randomizable` is not the best name. There are 
multiple dictionary definitions of "randomize" and one is "make unpredictable, 
unsystematic, or random in order or arrangement." Wikipedia gives at least five 
different contextual meanings for the word. What you're doing here is 
specifically **random sampling** and we can do better to clarify that, I think.

- While I agree that `RNG` can be cryptic, the alternative should be 
`RandomNumberGenerator` (as it's called in other languages); `RandomGenerator` 
is not quite accurate. Again, we're _consuming_ randomness to _generate_ 
numbers (or values of other type, based on the result of a generated number). 
We're not _generating_ randomness.


On Sun, Nov 5, 2017 at 6:33 PM, Alejandro Alonso 
<aalonso...@outlook.com<mailto:aalonso...@outlook.com>> wrote:
https://github.com/apple/swift-evolution/pull/760 is the current API and 
proposed solution.

- Alejandro

On Nov 5, 2017, 6:18 PM -0600, Xiaodi Wu 
<xiaodi...@gmail.com<mailto:xiaodi...@gmail.com>>, wrote:
My comments are directed to the "more up-to-date" document that you just linked 
to in your reply to Jon. Is that one outdated? If so, can you send a link to 
the updated proposal and implementation for which you're soliciting feedback?


On Sun, Nov 5, 2017 at 6:12 PM, Alejandro Alonso 
<aalonso...@outlook.com<mailto:aalonso...@outlook.com>> wrote:
The proposal and implementation have the current updated API. The link I sent 
Jon was the one I brought up a few weeks ago which is outdated now. The 
proposal answers all of your questions. As for `.random` being a function, some 
would argue that it behaves in the same way as `.first` and `.last` which are 
properties.

- Alejandro

On Nov 5, 2017, 6:07 PM -0600, Xiaodi Wu 
<xiaodi...@gmail.com<mailto:xiaodi...@gmail.com>>, wrote:
A few quick thoughts:

I know that there's been some discussion that `(1...10).random` is the best 
spelling, but I'd like to push back on that suggestion. When I want a random 
number, I tend to think of the type I want first ("I want a random integer") 
and then a range ("I want a random integer between a and b"), not the other way 
around. My intuition is that `Int.random(in:)` will be more discoverable, both 
on that basis and because it is more similar to other languages' syntax 
(`Math.random` in JavaScript and `randint` in NumPy, for example). It also has 
the advantage that the type is explicit, which I think is particularly useful 
in this case because the value itself is, well, random.

I would also argue that, `random` is most appropriately a method and not a 
property; there's no hard and fast rule for this, but the fact that the result 
is stochastic suggests (to me) that it's not a "property" of the range (or, for 
that matter, of the type).

I would reiterate here my qualms about `Source` being the term used for a 
generator. These types are not a _source_ of entropy but rather a _consumer_ of 
entropy.

`UnsafeRandomSource` needs to be renamed; "unsafe" has a specific meaning in 
Swift--that is, memory safety, and this is not it. Moreover, it's questionable 
whether this protocol is useful in any sense. What useful generic algorithms 
can one write with such a protocol?

`XoroshiroRandom` cannot be seeded by any `Numeric` value; depending on the 
specific algorithm it needs a seed of a specific bit width. If you default the 
shared instance to being seeded with an `Int` then you will have to have 
distinct implementations for 32-bit and 64-bit platforms. This is unadvisable. 
On that note, your `UnsafeRandomSource` needs to have an associated type and 
not a generic `` for the seed.

The default random number generator should be cryptographically secure; 
however, it's not clear to me that it should be device random.

I agree with others that alternative random number generators other than the 
default RNG (and, if not default, possibly also the device RNG) should be 
accommodated by the protocol hierarchy but not necessarily supplied in the 
stdlib.

The term `Randomizable` means something specific which is not how it's used in 
your proposed protocol.

There's still the open question, not answered, about how requesting an instance 
of the hardware RNG behaves when there's insufficient or no entropy. Does it 
return nil, throw, trap, or wait? The proposed API does not clarify this point, 
although based on the method signature it cannot return nil or throw. Trapping 
might be acceptable but I'd be 

Re: [swift-evolution] [Proposal] Random Unification

2017-11-05 Thread Alejandro Alonso via swift-evolution
`T?` because it no longer needs to 
parallel `Int.random`.

* * *

More in the bikeshedding arena, I take issue with some of the names:

- I reiterate my comment that `Randomizable` is not the best name. There are 
multiple dictionary definitions of "randomize" and one is "make unpredictable, 
unsystematic, or random in order or arrangement." Wikipedia gives at least five 
different contextual meanings for the word. What you're doing here is 
specifically **random sampling** and we can do better to clarify that, I think.

- While I agree that `RNG` can be cryptic, the alternative should be 
`RandomNumberGenerator` (as it's called in other languages); `RandomGenerator` 
is not quite accurate. Again, we're _consuming_ randomness to _generate_ 
numbers (or values of other type, based on the result of a generated number). 
We're not _generating_ randomness.


On Sun, Nov 5, 2017 at 6:33 PM, Alejandro Alonso 
<aalonso...@outlook.com<mailto:aalonso...@outlook.com>> wrote:
https://github.com/apple/swift-evolution/pull/760 is the current API and 
proposed solution.

- Alejandro

On Nov 5, 2017, 6:18 PM -0600, Xiaodi Wu 
<xiaodi...@gmail.com<mailto:xiaodi...@gmail.com>>, wrote:
My comments are directed to the "more up-to-date" document that you just linked 
to in your reply to Jon. Is that one outdated? If so, can you send a link to 
the updated proposal and implementation for which you're soliciting feedback?


On Sun, Nov 5, 2017 at 6:12 PM, Alejandro Alonso 
<aalonso...@outlook.com<mailto:aalonso...@outlook.com>> wrote:
The proposal and implementation have the current updated API. The link I sent 
Jon was the one I brought up a few weeks ago which is outdated now. The 
proposal answers all of your questions. As for `.random` being a function, some 
would argue that it behaves in the same way as `.first` and `.last` which are 
properties.

- Alejandro

On Nov 5, 2017, 6:07 PM -0600, Xiaodi Wu 
<xiaodi...@gmail.com<mailto:xiaodi...@gmail.com>>, wrote:
A few quick thoughts:

I know that there's been some discussion that `(1...10).random` is the best 
spelling, but I'd like to push back on that suggestion. When I want a random 
number, I tend to think of the type I want first ("I want a random integer") 
and then a range ("I want a random integer between a and b"), not the other way 
around. My intuition is that `Int.random(in:)` will be more discoverable, both 
on that basis and because it is more similar to other languages' syntax 
(`Math.random` in JavaScript and `randint` in NumPy, for example). It also has 
the advantage that the type is explicit, which I think is particularly useful 
in this case because the value itself is, well, random.

I would also argue that, `random` is most appropriately a method and not a 
property; there's no hard and fast rule for this, but the fact that the result 
is stochastic suggests (to me) that it's not a "property" of the range (or, for 
that matter, of the type).

I would reiterate here my qualms about `Source` being the term used for a 
generator. These types are not a _source_ of entropy but rather a _consumer_ of 
entropy.

`UnsafeRandomSource` needs to be renamed; "unsafe" has a specific meaning in 
Swift--that is, memory safety, and this is not it. Moreover, it's questionable 
whether this protocol is useful in any sense. What useful generic algorithms 
can one write with such a protocol?

`XoroshiroRandom` cannot be seeded by any `Numeric` value; depending on the 
specific algorithm it needs a seed of a specific bit width. If you default the 
shared instance to being seeded with an `Int` then you will have to have 
distinct implementations for 32-bit and 64-bit platforms. This is unadvisable. 
On that note, your `UnsafeRandomSource` needs to have an associated type and 
not a generic `` for the seed.

The default random number generator should be cryptographically secure; 
however, it's not clear to me that it should be device random.

I agree with others that alternative random number generators other than the 
default RNG (and, if not default, possibly also the device RNG) should be 
accommodated by the protocol hierarchy but not necessarily supplied in the 
stdlib.

The term `Randomizable` means something specific which is not how it's used in 
your proposed protocol.

There's still the open question, not answered, about how requesting an instance 
of the hardware RNG behaves when there's insufficient or no entropy. Does it 
return nil, throw, trap, or wait? The proposed API does not clarify this point, 
although based on the method signature it cannot return nil or throw. Trapping 
might be acceptable but I'd be interested to hear your take as to why it is 
preferable.


On Sun, Nov 5, 2017 at 4:43 PM, Alejandro Alonso via swift-evolution 
<swift-evolution@swift.org<mailto:swift-evolution@swift.org>> wrote:
For the proof of concept, I had accid

Re: [swift-evolution] [Proposal] Random Unification

2017-11-05 Thread Alejandro Alonso via swift-evolution
<mailto:aalonso...@outlook.com>> wrote:
https://github.com/apple/swift-evolution/pull/760 is the current API and 
proposed solution.

- Alejandro

On Nov 5, 2017, 6:18 PM -0600, Xiaodi Wu 
<xiaodi...@gmail.com<mailto:xiaodi...@gmail.com>>, wrote:
My comments are directed to the "more up-to-date" document that you just linked 
to in your reply to Jon. Is that one outdated? If so, can you send a link to 
the updated proposal and implementation for which you're soliciting feedback?


On Sun, Nov 5, 2017 at 6:12 PM, Alejandro Alonso 
<aalonso...@outlook.com<mailto:aalonso...@outlook.com>> wrote:
The proposal and implementation have the current updated API. The link I sent 
Jon was the one I brought up a few weeks ago which is outdated now. The 
proposal answers all of your questions. As for `.random` being a function, some 
would argue that it behaves in the same way as `.first` and `.last` which are 
properties.

- Alejandro

On Nov 5, 2017, 6:07 PM -0600, Xiaodi Wu 
<xiaodi...@gmail.com<mailto:xiaodi...@gmail.com>>, wrote:
A few quick thoughts:

I know that there's been some discussion that `(1...10).random` is the best 
spelling, but I'd like to push back on that suggestion. When I want a random 
number, I tend to think of the type I want first ("I want a random integer") 
and then a range ("I want a random integer between a and b"), not the other way 
around. My intuition is that `Int.random(in:)` will be more discoverable, both 
on that basis and because it is more similar to other languages' syntax 
(`Math.random` in JavaScript and `randint` in NumPy, for example). It also has 
the advantage that the type is explicit, which I think is particularly useful 
in this case because the value itself is, well, random.

I would also argue that, `random` is most appropriately a method and not a 
property; there's no hard and fast rule for this, but the fact that the result 
is stochastic suggests (to me) that it's not a "property" of the range (or, for 
that matter, of the type).

I would reiterate here my qualms about `Source` being the term used for a 
generator. These types are not a _source_ of entropy but rather a _consumer_ of 
entropy.

`UnsafeRandomSource` needs to be renamed; "unsafe" has a specific meaning in 
Swift--that is, memory safety, and this is not it. Moreover, it's questionable 
whether this protocol is useful in any sense. What useful generic algorithms 
can one write with such a protocol?

`XoroshiroRandom` cannot be seeded by any `Numeric` value; depending on the 
specific algorithm it needs a seed of a specific bit width. If you default the 
shared instance to being seeded with an `Int` then you will have to have 
distinct implementations for 32-bit and 64-bit platforms. This is unadvisable. 
On that note, your `UnsafeRandomSource` needs to have an associated type and 
not a generic `` for the seed.

The default random number generator should be cryptographically secure; 
however, it's not clear to me that it should be device random.

I agree with others that alternative random number generators other than the 
default RNG (and, if not default, possibly also the device RNG) should be 
accommodated by the protocol hierarchy but not necessarily supplied in the 
stdlib.

The term `Randomizable` means something specific which is not how it's used in 
your proposed protocol.

There's still the open question, not answered, about how requesting an instance 
of the hardware RNG behaves when there's insufficient or no entropy. Does it 
return nil, throw, trap, or wait? The proposed API does not clarify this point, 
although based on the method signature it cannot return nil or throw. Trapping 
might be acceptable but I'd be interested to hear your take as to why it is 
preferable.


On Sun, Nov 5, 2017 at 4:43 PM, Alejandro Alonso via swift-evolution 
<swift-evolution@swift.org<mailto:swift-evolution@swift.org>> wrote:
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 
<jh...@gbis.com<mailto:jh...@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 `ran

Re: [swift-evolution] [Proposal] Random Unification

2017-11-05 Thread Alejandro Alonso via swift-evolution
https://github.com/apple/swift-evolution/pull/760 is the current API and 
proposed solution.

- Alejandro

On Nov 5, 2017, 6:18 PM -0600, Xiaodi Wu <xiaodi...@gmail.com>, wrote:
My comments are directed to the "more up-to-date" document that you just linked 
to in your reply to Jon. Is that one outdated? If so, can you send a link to 
the updated proposal and implementation for which you're soliciting feedback?


On Sun, Nov 5, 2017 at 6:12 PM, Alejandro Alonso 
<aalonso...@outlook.com<mailto:aalonso...@outlook.com>> wrote:
The proposal and implementation have the current updated API. The link I sent 
Jon was the one I brought up a few weeks ago which is outdated now. The 
proposal answers all of your questions. As for `.random` being a function, some 
would argue that it behaves in the same way as `.first` and `.last` which are 
properties.

- Alejandro

On Nov 5, 2017, 6:07 PM -0600, Xiaodi Wu 
<xiaodi...@gmail.com<mailto:xiaodi...@gmail.com>>, wrote:
A few quick thoughts:

I know that there's been some discussion that `(1...10).random` is the best 
spelling, but I'd like to push back on that suggestion. When I want a random 
number, I tend to think of the type I want first ("I want a random integer") 
and then a range ("I want a random integer between a and b"), not the other way 
around. My intuition is that `Int.random(in:)` will be more discoverable, both 
on that basis and because it is more similar to other languages' syntax 
(`Math.random` in JavaScript and `randint` in NumPy, for example). It also has 
the advantage that the type is explicit, which I think is particularly useful 
in this case because the value itself is, well, random.

I would also argue that, `random` is most appropriately a method and not a 
property; there's no hard and fast rule for this, but the fact that the result 
is stochastic suggests (to me) that it's not a "property" of the range (or, for 
that matter, of the type).

I would reiterate here my qualms about `Source` being the term used for a 
generator. These types are not a _source_ of entropy but rather a _consumer_ of 
entropy.

`UnsafeRandomSource` needs to be renamed; "unsafe" has a specific meaning in 
Swift--that is, memory safety, and this is not it. Moreover, it's questionable 
whether this protocol is useful in any sense. What useful generic algorithms 
can one write with such a protocol?

`XoroshiroRandom` cannot be seeded by any `Numeric` value; depending on the 
specific algorithm it needs a seed of a specific bit width. If you default the 
shared instance to being seeded with an `Int` then you will have to have 
distinct implementations for 32-bit and 64-bit platforms. This is unadvisable. 
On that note, your `UnsafeRandomSource` needs to have an associated type and 
not a generic `` for the seed.

The default random number generator should be cryptographically secure; 
however, it's not clear to me that it should be device random.

I agree with others that alternative random number generators other than the 
default RNG (and, if not default, possibly also the device RNG) should be 
accommodated by the protocol hierarchy but not necessarily supplied in the 
stdlib.

The term `Randomizable` means something specific which is not how it's used in 
your proposed protocol.

There's still the open question, not answered, about how requesting an instance 
of the hardware RNG behaves when there's insufficient or no entropy. Does it 
return nil, throw, trap, or wait? The proposed API does not clarify this point, 
although based on the method signature it cannot return nil or throw. Trapping 
might be acceptable but I'd be interested to hear your take as to why it is 
preferable.


On Sun, Nov 5, 2017 at 4:43 PM, Alejandro Alonso via swift-evolution 
<swift-evolution@swift.org<mailto:swift-evolution@swift.org>> wrote:
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 
<jh...@gbis.com<mailto:jh...@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.githu

Re: [swift-evolution] [Proposal] Random Unification

2017-11-05 Thread Alejandro Alonso via swift-evolution
The proposal and implementation have the current updated API. The link I sent 
Jon was the one I brought up a few weeks ago which is outdated now. The 
proposal answers all of your questions. As for `.random` being a function, some 
would argue that it behaves in the same way as `.first` and `.last` which are 
properties.

- Alejandro

On Nov 5, 2017, 6:07 PM -0600, Xiaodi Wu <xiaodi...@gmail.com>, wrote:
A few quick thoughts:

I know that there's been some discussion that `(1...10).random` is the best 
spelling, but I'd like to push back on that suggestion. When I want a random 
number, I tend to think of the type I want first ("I want a random integer") 
and then a range ("I want a random integer between a and b"), not the other way 
around. My intuition is that `Int.random(in:)` will be more discoverable, both 
on that basis and because it is more similar to other languages' syntax 
(`Math.random` in JavaScript and `randint` in NumPy, for example). It also has 
the advantage that the type is explicit, which I think is particularly useful 
in this case because the value itself is, well, random.

I would also argue that, `random` is most appropriately a method and not a 
property; there's no hard and fast rule for this, but the fact that the result 
is stochastic suggests (to me) that it's not a "property" of the range (or, for 
that matter, of the type).

I would reiterate here my qualms about `Source` being the term used for a 
generator. These types are not a _source_ of entropy but rather a _consumer_ of 
entropy.

`UnsafeRandomSource` needs to be renamed; "unsafe" has a specific meaning in 
Swift--that is, memory safety, and this is not it. Moreover, it's questionable 
whether this protocol is useful in any sense. What useful generic algorithms 
can one write with such a protocol?

`XoroshiroRandom` cannot be seeded by any `Numeric` value; depending on the 
specific algorithm it needs a seed of a specific bit width. If you default the 
shared instance to being seeded with an `Int` then you will have to have 
distinct implementations for 32-bit and 64-bit platforms. This is unadvisable. 
On that note, your `UnsafeRandomSource` needs to have an associated type and 
not a generic `` for the seed.

The default random number generator should be cryptographically secure; 
however, it's not clear to me that it should be device random.

I agree with others that alternative random number generators other than the 
default RNG (and, if not default, possibly also the device RNG) should be 
accommodated by the protocol hierarchy but not necessarily supplied in the 
stdlib.

The term `Randomizable` means something specific which is not how it's used in 
your proposed protocol.

There's still the open question, not answered, about how requesting an instance 
of the hardware RNG behaves when there's insufficient or no entropy. Does it 
return nil, throw, trap, or wait? The proposed API does not clarify this point, 
although based on the method signature it cannot return nil or throw. Trapping 
might be acceptable but I'd be interested to hear your take as to why it is 
preferable.


On Sun, Nov 5, 2017 at 4:43 PM, Alejandro Alonso via swift-evolution 
<swift-evolution@swift.org<mailto:swift-evolution@swift.org>> wrote:
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 
<jh...@gbis.com<mailto:jh...@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 

Re: [swift-evolution] [Proposal] Random Unification

2017-11-05 Thread Alejandro Alonso via 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 <jh...@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

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


Re: [swift-evolution] [Proposal] Random Unification

2017-11-05 Thread Alejandro Alonso via swift-evolution
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


Re: [swift-evolution] [Proposal] Random Unification

2017-10-05 Thread Alejandro Alonso via swift-evolution
Rather 0 ..< 0 my bad. I think if we include closedcountable, then there needs 
to be support for countable, but there are edge cases where users can input 
invalid ranges for countable.

Enviado desde mi iPhone

El oct. 5, 2017, a la(s) 12:22, Alejandro Alonso via swift-evolution 
<swift-evolution@swift.org<mailto:swift-evolution@swift.org>> escribió:

I agree with Ben here because users can still enter an invalid range with the 
static function. I.E. Int.random(in: 0 ... 0).
I would really prefer excluding these static functions from numeric types.

- Alejandro

El oct. 5, 2017, a la(s) 12:03, Nate Cook via swift-evolution 
<swift-evolution@swift.org<mailto:swift-evolution@swift.org>> escribió:

On Oct 5, 2017, at 11:30 AM, Ben Cohen via swift-evolution 
<swift-evolution@swift.org<mailto:swift-evolution@swift.org>> wrote:

On Oct 4, 2017, at 9:12 PM, Chris Lattner via swift-evolution 
<swift-evolution@swift.org<mailto:swift-evolution@swift.org>> wrote:

```
extension Int {
  static func random(in range: Countable{Closed}Range) -> Int
}

Nice.  Should these be initializers like:

extension Int {
  init(randomIn: Countable{Closed}Range)
}


I don’t see much of a case for making it it random(in: SpecificCollection) 
instead of genericCollection.random().

I see a couple points in favor of these static methods (or initializers) on the 
numeric types:

1) The collection method will need to return an optional to match the semantics 
of existing methods (like min()). If this is the only method available, every 
time someone needs a random value in the range 1...10, they’ll need to unwrap 
the result (with either force unwrapping, which people will complain about, or 
some kind of conditional binding, which is its own problem). Even if the 
semantics are the same (trapping on an empty range), the user experience of 
using a non-optional method will be better.

2) Floating-point ranges won’t get the collection method, so either we’ll have 
inconsistent APIs (random FP value is non-optional, random integer is optional) 
or we’ll make the FP API optional just to match. Both of those seem bad.

One possible reason is if you exclude half-open ranges, only having 
CountableClosedRange, then you don’t have to account for the possibility of an 
empty collection (via an optional or a trap) because they cannot be empty. But 
closed ranges aren’t the currency type – half-open ranges are. So it’d hit 
usability if you have to convert from one to t'other often.

Other possibility is discovery. But given the common use case is “random 
element from collection”, I don’t expect this to be an issue as it will quickly 
become common knowledge that this feature is available.

Agreed here—I don’t think discovery is really an issue between the two kinds. 
However, I don’t think the overlap in features (two ways to generate random 
integers) are a problem, especially as we’d have better alignment between 
integer and floating-point methods.

Nate
___
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


Re: [swift-evolution] [Proposal] Random Unification

2017-10-05 Thread Alejandro Alonso via swift-evolution
I agree with Ben here because users can still enter an invalid range with the 
static function. I.E. Int.random(in: 0 ... 0).
I would really prefer excluding these static functions from numeric types.

- Alejandro

El oct. 5, 2017, a la(s) 12:03, Nate Cook via swift-evolution 
> escribió:

On Oct 5, 2017, at 11:30 AM, Ben Cohen via swift-evolution 
> wrote:

On Oct 4, 2017, at 9:12 PM, Chris Lattner via swift-evolution 
> wrote:

```
extension Int {
  static func random(in range: Countable{Closed}Range) -> Int
}

Nice.  Should these be initializers like:

extension Int {
  init(randomIn: Countable{Closed}Range)
}


I don’t see much of a case for making it it random(in: SpecificCollection) 
instead of genericCollection.random().

I see a couple points in favor of these static methods (or initializers) on the 
numeric types:

1) The collection method will need to return an optional to match the semantics 
of existing methods (like min()). If this is the only method available, every 
time someone needs a random value in the range 1...10, they’ll need to unwrap 
the result (with either force unwrapping, which people will complain about, or 
some kind of conditional binding, which is its own problem). Even if the 
semantics are the same (trapping on an empty range), the user experience of 
using a non-optional method will be better.

2) Floating-point ranges won’t get the collection method, so either we’ll have 
inconsistent APIs (random FP value is non-optional, random integer is optional) 
or we’ll make the FP API optional just to match. Both of those seem bad.

One possible reason is if you exclude half-open ranges, only having 
CountableClosedRange, then you don’t have to account for the possibility of an 
empty collection (via an optional or a trap) because they cannot be empty. But 
closed ranges aren’t the currency type – half-open ranges are. So it’d hit 
usability if you have to convert from one to t'other often.

Other possibility is discovery. But given the common use case is “random 
element from collection”, I don’t expect this to be an issue as it will quickly 
become common knowledge that this feature is available.

Agreed here—I don’t think discovery is really an issue between the two kinds. 
However, I don’t think the overlap in features (two ways to generate random 
integers) are a problem, especially as we’d have better alignment between 
integer and floating-point methods.

Nate
___
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


Re: [swift-evolution] [Proposal] Random Unification

2017-10-04 Thread Alejandro Alonso via swift-evolution
I think this is a good idea. I start asking questions about what our default 
generator for linux will be if we use Darwin’s arc4random(3). Do we use Glibc’s 
random()? If so, what do we seed it with?

- Alejandro

On Oct 4, 2017, 6:26 PM -0500, Ben Cohen via swift-evolution 
, wrote:


On Sep 30, 2017, at 3:23 PM, Chris Lattner via swift-evolution 
> wrote:


On Sep 11, 2017, at 9:43 PM, Brent Royal-Gordon 
> wrote:

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

- 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.

+1 to this general plan!

This pretty much exactly matches my preferences.

If random numbers go into the std lib, they should  being able to customize the 
source of randomness for speed or test reproducibility, but default to 
something sensible without the user having to know it’s configurable. On Darwin 
that default should be based on arc4random(3). The std lib doesn’t need to 
provide other non-default random sources. Non-random sources for testing should 
be part of test frameworks and plug in easily.

The proposal should include shuffle and random element from collection, which 
are much-requested and not really the controversial part so won't hold up the 
overall progress of the proposal.

(and no need for distributions other than uniform IMO,  or otherwise)


-Chris


___
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


Re: [swift-evolution] [Proposal] Random Unification

2017-10-03 Thread Alejandro Alonso via swift-evolution
I really like the schedule here. After reading for a while, I do agree with 
Brent that stdlib should very primitive in functionality that it provides. I 
also agree that the most important part right now is designing the internal 
crypto on which the numeric types use to return their respected random number. 
On the discussion of how we should handle not enough entropy with the device 
random, from a users perspective it makes sense that calling .random should 
just give me a random number, but from a developers perspective I see Optional 
being the best choice here. While I think blocking could, in most cases, 
provide the user an easier API, we have to do this right and be safe here by 
providing a value that indicates that there is room for error here. As for the 
generator abstraction, I believe there should be a bare basic protocol that 
sets a layout for new generators and should be focusing on its requirements.

Whether or not RandomAccessCollection and MutableCollection should get .random 
and .shuffle/.shuffled in this first proposal is completely up in the air for 
me. It makes sense, to me, to include the .random in this proposal and open 
another one .shuffle/.shuffled, but I can see arguments that should say we 
create something separate for these two, or include all of it in this proposal.

- Alejandro

On Sep 27, 2017, 7:29 PM -0500, Xiaodi Wu , wrote:

On Wed, Sep 27, 2017 at 00:18 Félix Cloutier 
> wrote:
Le 26 sept. 2017 à 16:14, Xiaodi Wu 
> a écrit :

On Tue, Sep 26, 2017 at 11:26 AM, Félix Cloutier 
> wrote:

It's possible to use a CSPRNG-grade algorithm and seed it once to get a 
reproducible sequence, but when you use it as a CSPRNG, you typically feed 
entropy back into it at nondeterministic points to ensure that even if you 
started with a bad seed, you'll eventually get to an alright state. Unless you 
keep track of when entropy was mixed in and what the values were, you'll never 
get a reproducible CSPRNG.

We would give developers a false sense of security if we provided them with 
CSPRNG-grade algorithms that we called CSPRNGs and that they could seed 
themselves. Just because it says "crypto-secure" in the name doesn't mean that 
it'll be crypto-secure if it's seeded with time(). Therefore, "reproducible" vs 
"non-reproducible" looks like a good distinction to me.

I disagree here, in two respects:

First, whether or not a particular PRNG is cryptographically secure is an 
intrinsic property of the algorithm; whether it's "reproducible" or not is 
determined by the published API. In other words, the distinction between CSPRNG 
vs. non-CSPRNG is important to document because it's semantics that cannot be 
deduced by the user otherwise, and it is an important one for writing secure 
code because it tells you whether an attacker can predict future outputs based 
only on observing past outputs. "Reproducible" in the sense of seedable or not 
is trivially noted by inspection of the published API, and it is rather 
immaterial to writing secure code.

Cryptographically secure is not a property that I'm comfortable applying to an 
algorithm. You cannot say that you've made a cryptographically secure thing 
just because you've used all the right algorithms: you also have to use them 
right, and one of the most critical components of a cryptographically secure 
PRNG is its seed.

A cryptographically secure algorithm isn’t sufficient, but it is necessary. 
That’s why it’s important to mark them as such. If I'm a careful developer, 
then it is absolutely important to me to know that I’m using a PRNG with a 
cryptographically secure algorithm, and that the particular implementation of 
that algorithm is correct and secure.

It is a *feature* of a lot of modern CSPRNGs that you can't seed them:


  *   You cannot seed or add entropy to std::random_device

Although std::random_device may in practice be backed by a software CSPRNG, 
IIUC, the intention is that it can provide access to a hardware 
non-deterministic source when available.


  *   You cannot seed or add entropy to CryptGenRandom
  *   You can only add entropy to /dev/(u)random
  *   You can only add entropy to BSD's arc4random

Ah, I see. I think we mean different things when we say PRNG. A PRNG is an 
entirely deterministic algorithm; the output is non-random and the algorithm 
itself requires no entropy. If a PRNG is seeded with a random sequence of bits, 
its output can "appear" to be random. A CSPRNG is a PRNG that fulfills certain 
criteria such that its output can be appropriate for use in cryptographic 
applications in place of a truly random sequence *if* the input to the CSPRNG 
is itself random.

The examples you give above *incorporate* a CSPRNG, environment entropy, and a 
set of rules about when to mix in additional entropy in 

Re: [swift-evolution] [Proposal] Random Unification

2017-09-11 Thread Alejandro Alonso via swift-evolution
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 <clatt...@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


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


Re: [swift-evolution] [Proposal] Random Unification

2017-09-08 Thread Alejandro Alonso via 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 <shaw...@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