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

2018-01-13 Thread Xiaodi Wu via swift-evolution
On Sat, Jan 13, 2018 at 10:29 PM, Erica Sadun via swift-evolution <
swift-evolution@swift.org> wrote:

> I think a full random implementation should be decoupled from Swift's
> standard library and generic random is overkill.
>
> In-language, I think pre-seeded random uniform (0 ..< 1,
> `Double.uniformRandom()`), random int (0 ..< max, `Int.uniform(max)`), and
> random index for indexed collection (`collection.randomIndex()`) is more
> than sufficient, assuming sufficient doc warnings that none of this is
> suitable for encryption or gambling.
>

Agree almost entirely, with the modification that if we limit ourselves to
these APIs it should be possible to implement in such a way that
suitability for encryption or gambling can be assured, which would be a
nice bonus but not a must-have.


> -- E
>
> On Jan 13, 2018, at 6:48 PM, Jonathan Hull via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> Basically, my point is that I want to be able to operate generically.
>
> On Jan 13, 2018, at 5:20 AM, Letanyan Arumugam 
> wrote:
>
>
> On 13 Jan 2018, at 02:24, Jonathan Hull  wrote:
>
> I think we have different definitions of consistency.  I am fine with the
> ergonomics of (0…100).random() as a convenience, but it really worries me
> here that everything is special cased.  Special cased things are fine for
> individual projects, but not the standard library.  We should make sure
> that the design is flexible and extensible, and that comes in part from
> having a consistent interface.
>
>
> I think we just want different consistencies. Mine is that I want the same
> mental model of having to get a random value from some explicit
> ’set’/’space’.
>
> Also, as I said before, we really shouldn’t be doing these crazy
> contortions to avoid ‘random() % 100’.  Instead we should look for that
> pattern and issue with a warning + fixit to change it to random(in:).  I
> think that will be much more effective in actually changing the behavior in
> the long run.
>
> Finally, tying everything to Range is extremely limiting.  I understand if
> we don’t want to add other types to the standard library, but I should be
> able to build on what we add to do it myself without having to reinvent the
> wheel for each type.  It is important to have a consistent story for these
> things (including multi-dimensional types) so that they can interoperate.
>
>
> As a stated above I don’t think of it as being tied to a range, but rather
> a set of possible values. If you want to have multi-dimensional generators,
> could you not add an extension on an array to generate a value treating the
> array's elements as constraints?
>
> Using CGPoint as an example with Nate’s api design of random.
>
> public enum ConstraintKind {
> case constant(T)
> case range(T, T)
> case custom((RandomNumberGenerator) -> T)
> }
>
> public enum PointConstraint {
> case x(ConstraintKind)
> case y(ConstraintKind)
> }
>
> extension Array where Element == PointConstraint {
> func random(from constraintKind: ConstraintKind,
> using generator: RandomNumberGenerator = Random.default
> ) -> CGFloat {
> switch constraintKind {
> case let .constant(a): return a
> case let .range(min, max): return (min...max).random(using: generator)
> case let .custom(f): return f(generator)
> }
> }
>
> public func createRandom(using generator: RandomNumberGenerator = Random.
> default) -> CGPoint {
> var x: CGFloat? = nil
> var y: CGFloat? = nil
>
> for constraint in self {
> switch constraint {
> case let .x(c): x = random(from: c, using: generator)
> case let .y(c): y = random(from: c, using: generator)
> }
> }
>
> return CGPoint(x: x ?? 0.0, y: y ?? 0.0)
> }
> }
>
> let pointSpace: [PointConstraint] = [
> .x(.range(2, 32.5)),
> .y(.constant(4))
> ]
>
> pointSpace.createRandom()
>
>
>
> This uses the idea that constraints create a space of possible CGPoint
> values that createRandom 'gets' from.
>
>
> You could make array conform to some ConstraintRandom protocol when we get
> conditional conformance.
>
> We really should be looking at GamePlayKit more for design inspiration.
> There are several use-cases there that are being blatantly ignored in this
> discussion.  For example, what if I want to randomly generate a game world
> (e.g. The square from The Battle For Polytopia” formerly “SuperTribes”)?
> Or what if I want an effect where it randomly fades in letters from a
> String.  (…).random() will be completely inadequate for these things.
>
> Thanks,
> Jon
>
>
>
> On Jan 12, 2018, at 5:11 AM, 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 thi

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

2018-01-13 Thread Erica Sadun via swift-evolution
I think a full random implementation should be decoupled from Swift's standard 
library and generic random is overkill.

In-language, I think pre-seeded random uniform (0 ..< 1, 
`Double.uniformRandom()`), random int (0 ..< max, `Int.uniform(max)`), and 
random index for indexed collection (`collection.randomIndex()`) is more than 
sufficient, assuming sufficient doc warnings that none of this is suitable for 
encryption or gambling.

-- E

> On Jan 13, 2018, at 6:48 PM, Jonathan Hull via swift-evolution 
>  wrote:
> 
> Basically, my point is that I want to be able to operate generically.
> 
>> On Jan 13, 2018, at 5:20 AM, Letanyan Arumugam > > wrote:
>> 
>> 
>>> On 13 Jan 2018, at 02:24, Jonathan Hull >> > wrote:
>>> 
>>> I think we have different definitions of consistency.  I am fine with the 
>>> ergonomics of (0…100).random() as a convenience, but it really worries me 
>>> here that everything is special cased.  Special cased things are fine for 
>>> individual projects, but not the standard library.  We should make sure 
>>> that the design is flexible and extensible, and that comes in part from 
>>> having a consistent interface.
>>> 
>> 
>> I think we just want different consistencies. Mine is that I want the same 
>> mental model of having to get a random value from some explicit 
>> ’set’/’space’.
>> 
>>> Also, as I said before, we really shouldn’t be doing these crazy 
>>> contortions to avoid ‘random() % 100’.  Instead we should look for that 
>>> pattern and issue with a warning + fixit to change it to random(in:).  I 
>>> think that will be much more effective in actually changing the behavior in 
>>> the long run.
>>> 
>>> Finally, tying everything to Range is extremely limiting.  I understand if 
>>> we don’t want to add other types to the standard library, but I should be 
>>> able to build on what we add to do it myself without having to reinvent the 
>>> wheel for each type.  It is important to have a consistent story for these 
>>> things (including multi-dimensional types) so that they can interoperate.
>>> 
>> 
>> As a stated above I don’t think of it as being tied to a range, but rather a 
>> set of possible values. If you want to have multi-dimensional generators, 
>> could you not add an extension on an array to generate a value treating the 
>> array's elements as constraints?
>> 
>> Using CGPoint as an example with Nate’s api design of random.
>> 
>> public enum ConstraintKind {
>>  case constant(T)
>>  case range(T, T)
>>  case custom((RandomNumberGenerator) -> T)
>> }
>> 
>> public enum PointConstraint {
>>  case x(ConstraintKind)
>>  case y(ConstraintKind)
>> }
>> 
>> extension Array where Element == PointConstraint {
>>  func random(from constraintKind: ConstraintKind,
>>  using generator: RandomNumberGenerator = Random.default
>>  ) -> CGFloat {
>>  switch constraintKind {
>>  case let .constant(a): return a
>>  case let .range(min, max): return (min...max).random(using: 
>> generator)
>>  case let .custom(f): return f(generator)
>>  }
>>  }
>>  
>>  public func createRandom(using generator: RandomNumberGenerator = 
>> Random.default) -> CGPoint {
>>  var x: CGFloat? = nil
>>  var y: CGFloat? = nil
>>  
>>  for constraint in self {
>>  switch constraint {
>>  case let .x(c): x = random(from: c, using: generator)
>>  case let .y(c): y = random(from: c, using: generator)
>>  }
>>  }
>>  
>>  return CGPoint(x: x ?? 0.0, y: y ?? 0.0)
>>  }
>> }
>> 
>> let pointSpace: [PointConstraint] = [
>>  .x(.range(2, 32.5)),
>>  .y(.constant(4))
>> ]
>> 
>> pointSpace.createRandom()
>> 
>> 
>> 
>> This uses the idea that constraints create a space of possible CGPoint 
>> values that createRandom 'gets' from.
>> 
>> 
>> You could make array conform to some ConstraintRandom protocol when we get 
>> conditional conformance.
>> 
>>> We really should be looking at GamePlayKit more for design inspiration.  
>>> There are several use-cases there that are being blatantly ignored in this 
>>> discussion.  For example, what if I want to randomly generate a game world 
>>> (e.g. The square from The Battle For Polytopia” formerly “SuperTribes”)?  
>>> Or what if I want an effect where it randomly fades in letters from a 
>>> String.  (…).random() will be completely inadequate for these things.
>>> 
>>> Thanks,
>>> Jon
>>> 
>>> 
>>> 
 On Jan 12, 2018, at 5:11 AM, 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 

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

2018-01-13 Thread David Waite via swift-evolution
For a range of 0..<(2< On Jan 13, 2018, at 7:41 PM, C. Keith Ray via swift-evolution 
>  wrote:
> 
> Could someone measure how bad the "random(32 bits) mod m" problem actually 
> is? It's prominent when the number of bits is close to m, eg 4 bits and m == 
> 3. Is it bad when bits == 32 and m is less than 2^16? Or bits == 64 and m is 
> less than 2^32?
> 
> C. Keith Ray
> https://leanpub.com/wepntk  <- buy my book?
> http://agilesolutionspace.blogspot.com/ 
> 
> twitter: @ckeithray
> http://www.thirdfoundationsw.com/keith_ray_resume_2014_long.pdf 
> 
> 
> On Jan 13, 2018, at 6:15 PM, Jonathan Hull via swift-evolution 
> mailto:swift-evolution@swift.org>> wrote:
> 
>> 
>>> On Jan 12, 2018, at 8:22 PM, Nate Cook >> > wrote:
>>> 
>>> On Jan 12, 2018, at 6:24 PM, Jonathan Hull via swift-evolution 
>>> mailto:swift-evolution@swift.org>> wrote:
>>> 
 I think we have different definitions of consistency.  I am fine with the 
 ergonomics of (0…100).random() as a convenience, but it really worries me 
 here that everything is special cased.  Special cased things are fine for 
 individual projects, but not the standard library.  We should make sure 
 that the design is flexible and extensible, and that comes in part from 
 having a consistent interface.
 
 Also, as I said before, we really shouldn’t be doing these crazy 
 contortions to avoid ‘random() % 100’.  Instead we should look for that 
 pattern and issue with a warning + fixit to change it to random(in:).  I 
 think that will be much more effective in actually changing the behavior 
 in the long run.
>>> 
>>> I’m not sure what contortions you’re describing—from what I’ve seen, the 
>>> proposal author is going to revise the proposal to have these ways of 
>>> generating individual values:
>> 
>> Mainly avoiding ‘random(using:)’ as a thing we can count on generically 
>> because of the fear of it being used with mod.  This makes random(using:) on 
>> Bool a one-off special case instead of a thing I can call on anything 
>> adhering to a protocol.
>> 
>> 
>>> In extensions to FixedWidthInteger and BinaryFloatingPoint:
>>> static func random(in: Range/ClosedRange, using: 
>>> RandomNumberGenerator) -> Self
>>> 
>>> In an extension to Bool:
>>> static func random(using: RandomNumberGenerator) -> Self
>>> 
>>> If someone still needs a full-width random value as a building-block for 
>>> generating random instances of other types, they should use the `next()` 
>>> method directly on a RandomNumberGenerator. In the example code you sent, 
>>> you could switch to using a RandomNumberGenerator instead of your 
>>> RandomSourceValue, or base your RandomSourceValue generation on a 
>>> RandomNumberGenerator instead of whatever random generator you’re using now.
>>> 
 Finally, tying everything to Range is extremely limiting.  I understand if 
 we don’t want to add other types to the standard library, but I should be 
 able to build on what we add to do it myself without having to reinvent 
 the wheel for each type.  It is important to have a consistent story for 
 these things (including multi-dimensional types) so that they can 
 interoperate.
 
 We really should be looking at GamePlayKit more for design inspiration.  
 There are several use-cases there that are being blatantly ignored in this 
 discussion.  For example, what if I want to randomly generate a game world 
 (e.g. The square from The Battle For Polytopia” formerly “SuperTribes”)?  
 Or what if I want an effect where it randomly fades in letters from a 
 String.  (…).random() will be completely inadequate for these things.
>>> 
>>> The goal at this point is to build into the standard library the basis for 
>>> all kinds of other use cases. Your library is one such example of something 
>>> that can be built on top of the protocol and methods that are being 
>>> proposed, as are a variety of other tasks, as I tried to show in the 
>>> playground.
>>> 
>>> What’s being proposed now is deliberately short of solving every need—the 
>>> additions would handle the hard stuff (correct and safe generation of 
>>> integers and floating-points, along with shuffling collections) and lay the 
>>> groundwork for other libraries to take things farther (by establishing the 
>>> RandomNumberGenerator, a default generator, and a pattern for their use).
>> 
>> I think we are mostly in agreement on this.  I don’t need the proposal to 
>> solve every need.  I would just really like to see something that those 
>> other things can be built on.  I don’t expect other types to conform out of 
>> the box, but I want the types that I add conformance to to be able to 
>> interoperate with machinery that others build around randomness.
>> 
>> For example, if we instead went with

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

2018-01-13 Thread C. Keith Ray via swift-evolution
Could someone measure how bad the "random(32 bits) mod m" problem actually is? 
It's prominent when the number of bits is close to m, eg 4 bits and m == 3. Is 
it bad when bits == 32 and m is less than 2^16? Or bits == 64 and m is less 
than 2^32?

C. Keith Ray
https://leanpub.com/wepntk <- buy my book?
http://agilesolutionspace.blogspot.com/
twitter: @ckeithray
http://www.thirdfoundationsw.com/keith_ray_resume_2014_long.pdf

> On Jan 13, 2018, at 6:15 PM, Jonathan Hull via swift-evolution 
>  wrote:
> 
> 
>> On Jan 12, 2018, at 8:22 PM, Nate Cook  wrote:
>> 
>> On Jan 12, 2018, at 6:24 PM, Jonathan Hull via swift-evolution 
>>  wrote:
>> 
>>> I think we have different definitions of consistency.  I am fine with the 
>>> ergonomics of (0…100).random() as a convenience, but it really worries me 
>>> here that everything is special cased.  Special cased things are fine for 
>>> individual projects, but not the standard library.  We should make sure 
>>> that the design is flexible and extensible, and that comes in part from 
>>> having a consistent interface.
>>> 
>>> Also, as I said before, we really shouldn’t be doing these crazy 
>>> contortions to avoid ‘random() % 100’.  Instead we should look for that 
>>> pattern and issue with a warning + fixit to change it to random(in:).  I 
>>> think that will be much more effective in actually changing the behavior in 
>>> the long run.
>> 
>> I’m not sure what contortions you’re describing—from what I’ve seen, the 
>> proposal author is going to revise the proposal to have these ways of 
>> generating individual values:
> 
> Mainly avoiding ‘random(using:)’ as a thing we can count on generically 
> because of the fear of it being used with mod.  This makes random(using:) on 
> Bool a one-off special case instead of a thing I can call on anything 
> adhering to a protocol.
> 
> 
>> In extensions to FixedWidthInteger and BinaryFloatingPoint:
>> static func random(in: Range/ClosedRange, using: 
>> RandomNumberGenerator) -> Self
>> 
>> In an extension to Bool:
>> static func random(using: RandomNumberGenerator) -> Self
>> 
>> If someone still needs a full-width random value as a building-block for 
>> generating random instances of other types, they should use the `next()` 
>> method directly on a RandomNumberGenerator. In the example code you sent, 
>> you could switch to using a RandomNumberGenerator instead of your 
>> RandomSourceValue, or base your RandomSourceValue generation on a 
>> RandomNumberGenerator instead of whatever random generator you’re using now.
>> 
>>> Finally, tying everything to Range is extremely limiting.  I understand if 
>>> we don’t want to add other types to the standard library, but I should be 
>>> able to build on what we add to do it myself without having to reinvent the 
>>> wheel for each type.  It is important to have a consistent story for these 
>>> things (including multi-dimensional types) so that they can interoperate.
>>> 
>>> We really should be looking at GamePlayKit more for design inspiration.  
>>> There are several use-cases there that are being blatantly ignored in this 
>>> discussion.  For example, what if I want to randomly generate a game world 
>>> (e.g. The square from The Battle For Polytopia” formerly “SuperTribes”)?  
>>> Or what if I want an effect where it randomly fades in letters from a 
>>> String.  (…).random() will be completely inadequate for these things.
>> 
>> The goal at this point is to build into the standard library the basis for 
>> all kinds of other use cases. Your library is one such example of something 
>> that can be built on top of the protocol and methods that are being 
>> proposed, as are a variety of other tasks, as I tried to show in the 
>> playground.
>> 
>> What’s being proposed now is deliberately short of solving every need—the 
>> additions would handle the hard stuff (correct and safe generation of 
>> integers and floating-points, along with shuffling collections) and lay the 
>> groundwork for other libraries to take things farther (by establishing the 
>> RandomNumberGenerator, a default generator, and a pattern for their use).
> 
> I think we are mostly in agreement on this.  I don’t need the proposal to 
> solve every need.  I would just really like to see something that those other 
> things can be built on.  I don’t expect other types to conform out of the 
> box, but I want the types that I add conformance to to be able to 
> interoperate with machinery that others build around randomness.
> 
> For example, if we instead went with Letanyan’s mental model of having to 
> define a space to select a random element from using a generator, that would 
> be perfectly fine for me, since we can conform Range to that protocol… and 
> then we can operate generically on objects which conform to it.
> 
> 
>> Speaking of GameplayKit, you can make GKRandomSource conform to 
>> RandomNumberGenerator in an extension, making all the GK... sources 
>> generators. If you’re already de

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

2018-01-13 Thread Jonathan Hull via swift-evolution

> On Jan 12, 2018, at 8:22 PM, Nate Cook  wrote:
> 
> On Jan 12, 2018, at 6:24 PM, Jonathan Hull via swift-evolution 
> mailto:swift-evolution@swift.org>> wrote:
> 
>> I think we have different definitions of consistency.  I am fine with the 
>> ergonomics of (0…100).random() as a convenience, but it really worries me 
>> here that everything is special cased.  Special cased things are fine for 
>> individual projects, but not the standard library.  We should make sure that 
>> the design is flexible and extensible, and that comes in part from having a 
>> consistent interface.
>> 
>> Also, as I said before, we really shouldn’t be doing these crazy contortions 
>> to avoid ‘random() % 100’.  Instead we should look for that pattern and 
>> issue with a warning + fixit to change it to random(in:).  I think that will 
>> be much more effective in actually changing the behavior in the long run.
> 
> I’m not sure what contortions you’re describing—from what I’ve seen, the 
> proposal author is going to revise the proposal to have these ways of 
> generating individual values:

Mainly avoiding ‘random(using:)’ as a thing we can count on generically because 
of the fear of it being used with mod.  This makes random(using:) on Bool a 
one-off special case instead of a thing I can call on anything adhering to a 
protocol.


> In extensions to FixedWidthInteger and BinaryFloatingPoint:
> static func random(in: Range/ClosedRange, using: RandomNumberGenerator) 
> -> Self
> 
> In an extension to Bool:
> static func random(using: RandomNumberGenerator) -> Self
> 
> If someone still needs a full-width random value as a building-block for 
> generating random instances of other types, they should use the `next()` 
> method directly on a RandomNumberGenerator. In the example code you sent, you 
> could switch to using a RandomNumberGenerator instead of your 
> RandomSourceValue, or base your RandomSourceValue generation on a 
> RandomNumberGenerator instead of whatever random generator you’re using now.
> 
>> Finally, tying everything to Range is extremely limiting.  I understand if 
>> we don’t want to add other types to the standard library, but I should be 
>> able to build on what we add to do it myself without having to reinvent the 
>> wheel for each type.  It is important to have a consistent story for these 
>> things (including multi-dimensional types) so that they can interoperate.
>> 
>> We really should be looking at GamePlayKit more for design inspiration.  
>> There are several use-cases there that are being blatantly ignored in this 
>> discussion.  For example, what if I want to randomly generate a game world 
>> (e.g. The square from The Battle For Polytopia” formerly “SuperTribes”)?  Or 
>> what if I want an effect where it randomly fades in letters from a String.  
>> (…).random() will be completely inadequate for these things.
> 
> The goal at this point is to build into the standard library the basis for 
> all kinds of other use cases. Your library is one such example of something 
> that can be built on top of the protocol and methods that are being proposed, 
> as are a variety of other tasks, as I tried to show in the playground.
> 
> What’s being proposed now is deliberately short of solving every need—the 
> additions would handle the hard stuff (correct and safe generation of 
> integers and floating-points, along with shuffling collections) and lay the 
> groundwork for other libraries to take things farther (by establishing the 
> RandomNumberGenerator, a default generator, and a pattern for their use).

I think we are mostly in agreement on this.  I don’t need the proposal to solve 
every need.  I would just really like to see something that those other things 
can be built on.  I don’t expect other types to conform out of the box, but I 
want the types that I add conformance to to be able to interoperate with 
machinery that others build around randomness.

For example, if we instead went with Letanyan’s mental model of having to 
define a space to select a random element from using a generator, that would be 
perfectly fine for me, since we can conform Range to that protocol… and then we 
can operate generically on objects which conform to it.


> Speaking of GameplayKit, you can make GKRandomSource conform to 
> RandomNumberGenerator in an extension, making all the GK... sources 
> generators. If you’re already depending on those random sources, you’d still 
> have access to them with the proposed model.

Agreed.  I was thinking someone was removing the ‘using:’ variant from the 
proposal for some reason.

Thanks,
Jon


> 
> Nate
> 
>> Thanks,
>> Jon
>> 
>> 
>> 
>>> On Jan 12, 2018, at 5:11 AM, 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 
>>

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

2018-01-13 Thread Jonathan Hull via swift-evolution
Basically, my point is that I want to be able to operate generically.

> On Jan 13, 2018, at 5:20 AM, Letanyan Arumugam  wrote:
> 
> 
>> On 13 Jan 2018, at 02:24, Jonathan Hull > > wrote:
>> 
>> I think we have different definitions of consistency.  I am fine with the 
>> ergonomics of (0…100).random() as a convenience, but it really worries me 
>> here that everything is special cased.  Special cased things are fine for 
>> individual projects, but not the standard library.  We should make sure that 
>> the design is flexible and extensible, and that comes in part from having a 
>> consistent interface.
>> 
> 
> I think we just want different consistencies. Mine is that I want the same 
> mental model of having to get a random value from some explicit ’set’/’space’.
> 
>> Also, as I said before, we really shouldn’t be doing these crazy contortions 
>> to avoid ‘random() % 100’.  Instead we should look for that pattern and 
>> issue with a warning + fixit to change it to random(in:).  I think that will 
>> be much more effective in actually changing the behavior in the long run.
>> 
>> Finally, tying everything to Range is extremely limiting.  I understand if 
>> we don’t want to add other types to the standard library, but I should be 
>> able to build on what we add to do it myself without having to reinvent the 
>> wheel for each type.  It is important to have a consistent story for these 
>> things (including multi-dimensional types) so that they can interoperate.
>> 
> 
> As a stated above I don’t think of it as being tied to a range, but rather a 
> set of possible values. If you want to have multi-dimensional generators, 
> could you not add an extension on an array to generate a value treating the 
> array's elements as constraints?
> 
> Using CGPoint as an example with Nate’s api design of random.
> 
> public enum ConstraintKind {
>   case constant(T)
>   case range(T, T)
>   case custom((RandomNumberGenerator) -> T)
> }
> 
> public enum PointConstraint {
>   case x(ConstraintKind)
>   case y(ConstraintKind)
> }
> 
> extension Array where Element == PointConstraint {
>   func random(from constraintKind: ConstraintKind,
>   using generator: RandomNumberGenerator = Random.default
>   ) -> CGFloat {
>   switch constraintKind {
>   case let .constant(a): return a
>   case let .range(min, max): return (min...max).random(using: 
> generator)
>   case let .custom(f): return f(generator)
>   }
>   }
>   
>   public func createRandom(using generator: RandomNumberGenerator = 
> Random.default) -> CGPoint {
>   var x: CGFloat? = nil
>   var y: CGFloat? = nil
>   
>   for constraint in self {
>   switch constraint {
>   case let .x(c): x = random(from: c, using: generator)
>   case let .y(c): y = random(from: c, using: generator)
>   }
>   }
>   
>   return CGPoint(x: x ?? 0.0, y: y ?? 0.0)
>   }
> }
> 
> let pointSpace: [PointConstraint] = [
>   .x(.range(2, 32.5)),
>   .y(.constant(4))
> ]
> 
> pointSpace.createRandom()
> 
> 
> 
> This uses the idea that constraints create a space of possible CGPoint values 
> that createRandom 'gets' from.
> 
> 
> You could make array conform to some ConstraintRandom protocol when we get 
> conditional conformance.
> 
>> We really should be looking at GamePlayKit more for design inspiration.  
>> There are several use-cases there that are being blatantly ignored in this 
>> discussion.  For example, what if I want to randomly generate a game world 
>> (e.g. The square from The Battle For Polytopia” formerly “SuperTribes”)?  Or 
>> what if I want an effect where it randomly fades in letters from a String.  
>> (…).random() will be completely inadequate for these things.
>> 
>> Thanks,
>> Jon
>> 
>> 
>> 
>>> On Jan 12, 2018, at 5:11 AM, 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:

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

2018-01-13 Thread Jonathan Hull via swift-evolution

> On Jan 13, 2018, at 5:20 AM, Letanyan Arumugam  wrote:
> 
> 
>> On 13 Jan 2018, at 02:24, Jonathan Hull > > wrote:
>> 
>> I think we have different definitions of consistency.  I am fine with the 
>> ergonomics of (0…100).random() as a convenience, but it really worries me 
>> here that everything is special cased.  Special cased things are fine for 
>> individual projects, but not the standard library.  We should make sure that 
>> the design is flexible and extensible, and that comes in part from having a 
>> consistent interface.
>> 
> 
> I think we just want different consistencies. Mine is that I want the same 
> mental model of having to get a random value from some explicit ’set’/’space’.

I could get on board with that model pretty easily, but I would like to see a 
proposal which makes it explicit (and has a path for other things to declare 
themselves as one of these spaces).  Something like:

protocol RandomSpace {
func randomElement(using: RandomNumberGenerator)
}

...and then conform Range to it (as opposed to providing random() only for two 
special cases of range).

It would also be interesting to explore the concept of these constrained spaces 
in general, and how they might be useful in other ways… but that is probably a 
different proposal.

Thanks,
Jon


>> Also, as I said before, we really shouldn’t be doing these crazy contortions 
>> to avoid ‘random() % 100’.  Instead we should look for that pattern and 
>> issue with a warning + fixit to change it to random(in:).  I think that will 
>> be much more effective in actually changing the behavior in the long run.
>> 
>> Finally, tying everything to Range is extremely limiting.  I understand if 
>> we don’t want to add other types to the standard library, but I should be 
>> able to build on what we add to do it myself without having to reinvent the 
>> wheel for each type.  It is important to have a consistent story for these 
>> things (including multi-dimensional types) so that they can interoperate.
>> 
> 
> As a stated above I don’t think of it as being tied to a range, but rather a 
> set of possible values. If you want to have multi-dimensional generators, 
> could you not add an extension on an array to generate a value treating the 
> array's elements as constraints?
> 
> Using CGPoint as an example with Nate’s api design of random.
> 
> public enum ConstraintKind {
>   case constant(T)
>   case range(T, T)
>   case custom((RandomNumberGenerator) -> T)
> }
> 
> public enum PointConstraint {
>   case x(ConstraintKind)
>   case y(ConstraintKind)
> }
> 
> extension Array where Element == PointConstraint {
>   func random(from constraintKind: ConstraintKind,
>   using generator: RandomNumberGenerator = Random.default
>   ) -> CGFloat {
>   switch constraintKind {
>   case let .constant(a): return a
>   case let .range(min, max): return (min...max).random(using: 
> generator)
>   case let .custom(f): return f(generator)
>   }
>   }
>   
>   public func createRandom(using generator: RandomNumberGenerator = 
> Random.default) -> CGPoint {
>   var x: CGFloat? = nil
>   var y: CGFloat? = nil
>   
>   for constraint in self {
>   switch constraint {
>   case let .x(c): x = random(from: c, using: generator)
>   case let .y(c): y = random(from: c, using: generator)
>   }
>   }
>   
>   return CGPoint(x: x ?? 0.0, y: y ?? 0.0)
>   }
> }
> 
> let pointSpace: [PointConstraint] = [
>   .x(.range(2, 32.5)),
>   .y(.constant(4))
> ]
> 
> pointSpace.createRandom()
> 
> 
> 
> This uses the idea that constraints create a space of possible CGPoint values 
> that createRandom 'gets' from.
> 
> 
> You could make array conform to some ConstraintRandom protocol when we get 
> conditional conformance.
> 
>> We really should be looking at GamePlayKit more for design inspiration.  
>> There are several use-cases there that are being blatantly ignored in this 
>> discussion.  For example, what if I want to randomly generate a game world 
>> (e.g. The square from The Battle For Polytopia” formerly “SuperTribes”)?  Or 
>> what if I want an effect where it randomly fades in letters from a String.  
>> (…).random() will be completely inadequate for these things.
>> 
>> Thanks,
>> Jon
>> 
>> 
>> 
>>> On Jan 12, 2018, at 5:11 AM, 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 jus

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

2018-01-13 Thread Letanyan Arumugam via swift-evolution

> On 13 Jan 2018, at 02:24, Jonathan Hull  wrote:
> 
> I think we have different definitions of consistency.  I am fine with the 
> ergonomics of (0…100).random() as a convenience, but it really worries me 
> here that everything is special cased.  Special cased things are fine for 
> individual projects, but not the standard library.  We should make sure that 
> the design is flexible and extensible, and that comes in part from having a 
> consistent interface.
> 

I think we just want different consistencies. Mine is that I want the same 
mental model of having to get a random value from some explicit ’set’/’space’.

> Also, as I said before, we really shouldn’t be doing these crazy contortions 
> to avoid ‘random() % 100’.  Instead we should look for that pattern and issue 
> with a warning + fixit to change it to random(in:).  I think that will be 
> much more effective in actually changing the behavior in the long run.
> 
> Finally, tying everything to Range is extremely limiting.  I understand if we 
> don’t want to add other types to the standard library, but I should be able 
> to build on what we add to do it myself without having to reinvent the wheel 
> for each type.  It is important to have a consistent story for these things 
> (including multi-dimensional types) so that they can interoperate.
> 

As a stated above I don’t think of it as being tied to a range, but rather a 
set of possible values. If you want to have multi-dimensional generators, could 
you not add an extension on an array to generate a value treating the array's 
elements as constraints?

Using CGPoint as an example with Nate’s api design of random.

public enum ConstraintKind {
case constant(T)
case range(T, T)
case custom((RandomNumberGenerator) -> T)
}

public enum PointConstraint {
case x(ConstraintKind)
case y(ConstraintKind)
}

extension Array where Element == PointConstraint {
func random(from constraintKind: ConstraintKind,
using generator: RandomNumberGenerator = Random.default
) -> CGFloat {
switch constraintKind {
case let .constant(a): return a
case let .range(min, max): return (min...max).random(using: 
generator)
case let .custom(f): return f(generator)
}
}

public func createRandom(using generator: RandomNumberGenerator = 
Random.default) -> CGPoint {
var x: CGFloat? = nil
var y: CGFloat? = nil

for constraint in self {
switch constraint {
case let .x(c): x = random(from: c, using: generator)
case let .y(c): y = random(from: c, using: generator)
}
}

return CGPoint(x: x ?? 0.0, y: y ?? 0.0)
}
}

let pointSpace: [PointConstraint] = [
.x(.range(2, 32.5)),
.y(.constant(4))
]

pointSpace.createRandom()



This uses the idea that constraints create a space of possible CGPoint values 
that createRandom 'gets' from.


You could make array conform to some ConstraintRandom protocol when we get 
conditional conformance.

> We really should be looking at GamePlayKit more for design inspiration.  
> There are several use-cases there that are being blatantly ignored in this 
> discussion.  For example, what if I want to randomly generate a game world 
> (e.g. The square from The Battle For Polytopia” formerly “SuperTribes”)?  Or 
> what if I want an effect where it randomly fades in letters from a String.  
> (…).random() will be completely inadequate for these things.
> 
> Thanks,
> Jon
> 
> 
> 
>> On Jan 12, 2018, at 5:11 AM, 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 oth

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

2018-01-13 Thread Xiaodi Wu via swift-evolution
On Fri, Jan 12, 2018 at 10:23 PM, Nate Cook via swift-evolution <
swift-evolution@swift.org> wrote:

> On Jan 12, 2018, at 6:24 PM, Jonathan Hull via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> I think we have different definitions of consistency.  I am fine with the
> ergonomics of (0…100).random() as a convenience, but it really worries me
> here that everything is special cased.  Special cased things are fine for
> individual projects, but not the standard library.  We should make sure
> that the design is flexible and extensible, and that comes in part from
> having a consistent interface.
>
> Also, as I said before, we really shouldn’t be doing these crazy
> contortions to avoid ‘random() % 100’.  Instead we should look for that
> pattern and issue with a warning + fixit to change it to random(in:).  I
> think that will be much more effective in actually changing the behavior in
> the long run.
>
>
> I’m not sure what contortions you’re describing—from what I’ve seen, the
> proposal author is going to revise the proposal to have these ways of
> generating individual values:
>
> In extensions to FixedWidthInteger and BinaryFloatingPoint:
> static func random(in: Range/ClosedRange, using:
> RandomNumberGenerator) -> Self
>
> In an extension to Bool:
> static func random(using: RandomNumberGenerator) -> Self
>

I neglected to comment initially, but this particular extension on Bool
doesn't hold its own weight.

If the desire is for a fair coin, it would be a synonym for a one-liner
that's exquisitely readable: `Double.random(in: 0..<1) < 0.5`.

But of course there will be interest for biased coins, for which an
additional API would be needed, the spelling of which is (a) not easy to
get right and (b) never going to be more readable than the alternative.
Observe how, given `Double.random(in: 0..<1) < 0.25`, it is instantly
obvious the likelihood of `true` vs. `false`.

Put another way, `Bool.random` is not a primitive and doesn't need to be a
standard library API.


>
> If someone still needs a full-width random value as a building-block for
> generating random instances of other types, they should use the `next()`
> method directly on a RandomNumberGenerator. In the example code you sent,
> you could switch to using a RandomNumberGenerator instead of your
> RandomSourceValue, or base your RandomSourceValue generation on a
> RandomNumberGenerator instead of whatever random generator you’re using now.
>
> Finally, tying everything to Range is extremely limiting.  I understand if
> we don’t want to add other types to the standard library, but I should be
> able to build on what we add to do it myself without having to reinvent the
> wheel for each type.  It is important to have a consistent story for these
> things (including multi-dimensional types) so that they can interoperate.
>
>
> We really should be looking at GamePlayKit more for design inspiration.
> There are several use-cases there that are being blatantly ignored in this
> discussion.  For example, what if I want to randomly generate a game world
> (e.g. The square from The Battle For Polytopia” formerly “SuperTribes”)?
> Or what if I want an effect where it randomly fades in letters from a
> String.  (…).random() will be completely inadequate for these things.
>
>
> The goal at this point is to build into the standard library the basis for
> all kinds of other use cases. Your library is one such example of something
> that can be built on top of the protocol and methods that are being
> proposed, as are a variety of other tasks, as I tried to show in the
> playground.
>
> What’s being proposed now is deliberately short of solving every need—the
> additions would handle the hard stuff (correct and safe generation of
> integers and floating-points, along with shuffling collections) and lay the
> groundwork for other libraries to take things farther (by establishing the
> RandomNumberGenerator, a default generator, and a pattern for their use).
>
> Speaking of GameplayKit, you can make GKRandomSource conform to
> RandomNumberGenerator in an extension, making all the GK... sources
> generators. If you’re already depending on those random sources, you’d
> still have access to them with the proposed model.
>
> Nate
>
> Thanks,
> Jon
>
>
>
> On Jan 12, 2018, at 5:11 AM, 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 les

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

2018-01-12 Thread Karl Wagner via swift-evolution


> On 13. Jan 2018, at 05:23, Nate Cook via swift-evolution 
>  wrote:
> 
> On Jan 12, 2018, at 6:24 PM, Jonathan Hull via swift-evolution 
> mailto:swift-evolution@swift.org>> wrote:
> 
>> I think we have different definitions of consistency.  I am fine with the 
>> ergonomics of (0…100).random() as a convenience, but it really worries me 
>> here that everything is special cased.  Special cased things are fine for 
>> individual projects, but not the standard library.  We should make sure that 
>> the design is flexible and extensible, and that comes in part from having a 
>> consistent interface.
>> 
>> Also, as I said before, we really shouldn’t be doing these crazy contortions 
>> to avoid ‘random() % 100’.  Instead we should look for that pattern and 
>> issue with a warning + fixit to change it to random(in:).  I think that will 
>> be much more effective in actually changing the behavior in the long run.
> 
> I’m not sure what contortions you’re describing—from what I’ve seen, the 
> proposal author is going to revise the proposal to have these ways of 
> generating individual values:
> 
> In extensions to FixedWidthInteger and BinaryFloatingPoint:
> static func random(in: Range/ClosedRange, using: RandomNumberGenerator) 
> -> Self
> 
> In an extension to Bool:
> static func random(using: RandomNumberGenerator) -> Self
> 
> If someone still needs a full-width random value as a building-block for 
> generating random instances of other types, they should use the `next()` 
> method directly on a RandomNumberGenerator. In the example code you sent, you 
> could switch to using a RandomNumberGenerator instead of your 
> RandomSourceValue, or base your RandomSourceValue generation on a 
> RandomNumberGenerator instead of whatever random generator you’re using now.

I’m not sure what the current most-recent proposal is, but I think that’s fine 
for a minimal API.

The only thing I would add would be a convenience function which accesses a 
random element from a RandomAccessCollection.

- Karl

> 
>> Finally, tying everything to Range is extremely limiting.  I understand if 
>> we don’t want to add other types to the standard library, but I should be 
>> able to build on what we add to do it myself without having to reinvent the 
>> wheel for each type.  It is important to have a consistent story for these 
>> things (including multi-dimensional types) so that they can interoperate.
>> 
>> We really should be looking at GamePlayKit more for design inspiration.  
>> There are several use-cases there that are being blatantly ignored in this 
>> discussion.  For example, what if I want to randomly generate a game world 
>> (e.g. The square from The Battle For Polytopia” formerly “SuperTribes”)?  Or 
>> what if I want an effect where it randomly fades in letters from a String.  
>> (…).random() will be completely inadequate for these things.
> 
> The goal at this point is to build into the standard library the basis for 
> all kinds of other use cases. Your library is one such example of something 
> that can be built on top of the protocol and methods that are being proposed, 
> as are a variety of other tasks, as I tried to show in the playground.
> 
> What’s being proposed now is deliberately short of solving every need—the 
> additions would handle the hard stuff (correct and safe generation of 
> integers and floating-points, along with shuffling collections) and lay the 
> groundwork for other libraries to take things farther (by establishing the 
> RandomNumberGenerator, a default generator, and a pattern for their use).
> 
> Speaking of GameplayKit, you can make GKRandomSource conform to 
> RandomNumberGenerator in an extension, making all the GK... sources 
> generators. If you’re already depending on those random sources, you’d still 
> have access to them with the proposed model.
> 
> Nate
> 
>> Thanks,
>> Jon
>> 
>> 
>> 
>>> On Jan 12, 2018, at 5:11 AM, 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 

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

2018-01-12 Thread Nate Cook via swift-evolution
> On Jan 12, 2018, at 6:24 PM, Jonathan Hull via swift-evolution 
>  wrote:
> 
> I think we have different definitions of consistency.  I am fine with the 
> ergonomics of (0…100).random() as a convenience, but it really worries me 
> here that everything is special cased.  Special cased things are fine for 
> individual projects, but not the standard library.  We should make sure that 
> the design is flexible and extensible, and that comes in part from having a 
> consistent interface.
> 
> Also, as I said before, we really shouldn’t be doing these crazy contortions 
> to avoid ‘random() % 100’.  Instead we should look for that pattern and issue 
> with a warning + fixit to change it to random(in:).  I think that will be 
> much more effective in actually changing the behavior in the long run.

I’m not sure what contortions you’re describing—from what I’ve seen, the 
proposal author is going to revise the proposal to have these ways of 
generating individual values:

In extensions to FixedWidthInteger and BinaryFloatingPoint:
static func random(in: Range/ClosedRange, using: RandomNumberGenerator) 
-> Self

In an extension to Bool:
static func random(using: RandomNumberGenerator) -> Self

If someone still needs a full-width random value as a building-block for 
generating random instances of other types, they should use the `next()` method 
directly on a RandomNumberGenerator. In the example code you sent, you could 
switch to using a RandomNumberGenerator instead of your RandomSourceValue, or 
base your RandomSourceValue generation on a RandomNumberGenerator instead of 
whatever random generator you’re using now.

> Finally, tying everything to Range is extremely limiting.  I understand if we 
> don’t want to add other types to the standard library, but I should be able 
> to build on what we add to do it myself without having to reinvent the wheel 
> for each type.  It is important to have a consistent story for these things 
> (including multi-dimensional types) so that they can interoperate.
> 
> We really should be looking at GamePlayKit more for design inspiration.  
> There are several use-cases there that are being blatantly ignored in this 
> discussion.  For example, what if I want to randomly generate a game world 
> (e.g. The square from The Battle For Polytopia” formerly “SuperTribes”)?  Or 
> what if I want an effect where it randomly fades in letters from a String.  
> (…).random() will be completely inadequate for these things.

The goal at this point is to build into the standard library the basis for all 
kinds of other use cases. Your library is one such example of something that 
can be built on top of the protocol and methods that are being proposed, as are 
a variety of other tasks, as I tried to show in the playground.

What’s being proposed now is deliberately short of solving every need—the 
additions would handle the hard stuff (correct and safe generation of integers 
and floating-points, along with shuffling collections) and lay the groundwork 
for other libraries to take things farther (by establishing the 
RandomNumberGenerator, a default generator, and a pattern for their use).

Speaking of GameplayKit, you can make GKRandomSource conform to 
RandomNumberGenerator in an extension, making all the GK... sources generators. 
If you’re already depending on those random sources, you’d still have access to 
them with the proposed model.

Nate

> Thanks,
> Jon
> 
> 
> 
>> On Jan 12, 2018, at 5:11 AM, 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

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

2018-01-12 Thread Jonathan Hull via swift-evolution

> On Jan 12, 2018, at 4:24 PM, Jonathan Hull  wrote:
> 
> Or what if I want an effect where it randomly fades in letters from a String.

Just to explain this example further.  I ran into this issue when trying to use 
arc4random to do this.  The eye is really sensitive to patterns in cases like 
this where it is represented visually.  I had to create my own RandomSource 
(see previous email) with a generator designed to make things less random (in a 
way that feels more random to the eye) to make this look ok. ___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2018-01-12 Thread Jonathan Hull via swift-evolution
I think we have different definitions of consistency.  I am fine with the 
ergonomics of (0…100).random() as a convenience, but it really worries me here 
that everything is special cased.  Special cased things are fine for individual 
projects, but not the standard library.  We should make sure that the design is 
flexible and extensible, and that comes in part from having a consistent 
interface.

Also, as I said before, we really shouldn’t be doing these crazy contortions to 
avoid ‘random() % 100’.  Instead we should look for that pattern and issue with 
a warning + fixit to change it to random(in:).  I think that will be much more 
effective in actually changing the behavior in the long run.

Finally, tying everything to Range is extremely limiting.  I understand if we 
don’t want to add other types to the standard library, but I should be able to 
build on what we add to do it myself without having to reinvent the wheel for 
each type.  It is important to have a consistent story for these things 
(including multi-dimensional types) so that they can interoperate.

We really should be looking at GamePlayKit more for design inspiration.  There 
are several use-cases there that are being blatantly ignored in this 
discussion.  For example, what if I want to randomly generate a game world 
(e.g. The square from The Battle For Polytopia” formerly “SuperTribes”)?  Or 
what if I want an effect where it randomly fades in letters from a String.  
(…).random() will be completely inadequate for these things.

Thanks,
Jon



> On Jan 12, 2018, at 5:11 AM, 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 
>> mailto:swift-evolution@swift.org>>, 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

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

2018-01-12 Thread Jonathan Hull via swift-evolution
We are doing crazy contortions to avoid the 'random % 100’ issue.  Why not just 
check for that pattern and issue a warning with a fixit to do it better?

I don’t think it is worth handicapping everything just to avoid this.

Thanks,
Jon
 
> On Jan 11, 2018, at 11:22 PM, Nate Cook via swift-evolution 
>  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..> justification for a static property on one of the Integer protocols as 
>> shorthand for that.” I believe this makes it perfectly justifiable for 
>> `.random()` on numeric types. This also creates a consistency with 
>> `Bool.random()` making it justifiable for this as well. 
>> 
>> We can do all of this without `Randomizable` as well! Add extension methods 
>> on `FixedWidthInteger`, `BinaryFloatingPoint`, and `Bool`. These will be the 
>> methods that crash on an empty range, but we can precondition here to 
>> provide helpful debugging for developers. You made reference to users using 
>> the range based api for a safe alternative if they needed optionals.
>> 
>> ```
>> // Here you can use something more runtime oriented (such as an array count)
>> guard let x = (0 ..< 5).random() else {
>>  fatalError(“not going to happen")
>> }
>> ```
>> 
>> I’m not too sure if you’ve had a change of heart, but I think the following 
>> is justifiable if we remove `Randomizable`.
>> 
>> Sample Syntax:
>> ```
>> // Full Int width (shorthand for Int.random(in: .min … .max))
>> Int.random()
>> 
>> // random int from [0, 10)
>> Int.random(in: 0 ..< 10)
>> 
>> // random double from [0, 1) (Modulo isn’t an issue here!)
>> Double.random()
>> 
>> // random double from [0, .pi)
>> Double.random(in: 0 ..< .pi)
>> 
>> // random boolean
>> Bool.random()
>> ```
>> 
>> This seems very consistent to me. The only inconsistency is with 
>> `Int.random()` covering the full width, and `Double.random()` covering only 
>> `[0, 1)`, but to me this functionality is very precedented in many other 
>> languages. Also by removing `Randomizable`, other data types like `Data` 
>> don’t have to conform to a protocol, but can just add a random initializer 
>> that fits its needs.
>> 
>> I think now is when people will start saying, “Int.random() bad, modulo 
>> bias, no no” x)
>> I see the potential for error here, but logically I’m thinking that so many 
>> other languages have this feature and I wonder if you think they all did it 
>> wrong too and shouldn’t have done so. This type of behavior is found in C, 
>> C++, C#, Java, etc. I agree with Jonathon in that maybe we could suggest a 
>> warning/fixit in Xcode.
>> 
>> tl;dr - Remove `Randomizable`, remove associated type on 
>> `RandomNumberGenerator`, be consistent with `.random()` with other 
>> properties and functions with every collection, preserve static `r

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 
mailto:natec...@apple.com>> wrote:

On Jan 11, 2018, at 9:17 PM, Alejandro Alonso 
mailto:aalonso...@outlook.com>> 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 
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 
mailto:swift-evolution@swift.org>> wrote:


On Dec 2, 2017, at 6:02 PM, Xiaodi Wu via swift-evolution 
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 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 sh

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 
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 
mailto:xiaodi...@gmail.com>> wrote:

On Thu, Jan 11, 2018 at 9:17 PM, Alejandro Alonso via swift-evolution 
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 
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 
mailto:swift-evolution@swift.org>> wrote:


On Dec 2, 2017, at 6:02 PM, Xiaodi Wu via swift-evolution 
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 the subtleties of insecure or 
pseudorandom numbers, I'm not sure

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 
mailto:letanya...@gmail.com>> 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 
mailto:aalonso...@outlook.com>> 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 
mailto:swift-evolution@swift.org>>, 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

   

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 
mailto:xiaodi...@gmail.com>> wrote:

On Thu, Jan 11, 2018 at 9:17 PM, Alejandro Alonso via swift-evolution 
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 
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 
mailto:swift-evolution@swift.org>> wrote:


On Dec 2, 2017, at 6:02 PM, Xiaodi Wu via swift-evolution 
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 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-expert

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

2018-01-12 Thread Letanyan Arumugam via swift-evolution
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 value:RandomSourceValue, 
>>> constraints:[String:RandomSourceConstraint])->Self
>

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

2018-01-11 Thread Nate Cook via swift-evolution
> 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.. justification for a static property on one of the Integer protocols as 
> shorthand for that.” I believe this makes it perfectly justifiable for 
> `.random()` on numeric types. This also creates a consistency with 
> `Bool.random()` making it justifiable for this as well. 
> 
> We can do all of this without `Randomizable` as well! Add extension methods 
> on `FixedWidthInteger`, `BinaryFloatingPoint`, and `Bool`. These will be the 
> methods that crash on an empty range, but we can precondition here to provide 
> helpful debugging for developers. You made reference to users using the range 
> based api for a safe alternative if they needed optionals.
> 
> ```
> // Here you can use something more runtime oriented (such as an array count)
> guard let x = (0 ..< 5).random() else {
>  fatalError(“not going to happen")
> }
> ```
> 
> I’m not too sure if you’ve had a change of heart, but I think the following 
> is justifiable if we remove `Randomizable`.
> 
> Sample Syntax:
> ```
> // Full Int width (shorthand for Int.random(in: .min … .max))
> Int.random()
> 
> // random int from [0, 10)
> Int.random(in: 0 ..< 10)
> 
> // random double from [0, 1) (Modulo isn’t an issue here!)
> Double.random()
> 
> // random double from [0, .pi)
> Double.random(in: 0 ..< .pi)
> 
> // random boolean
> Bool.random()
> ```
> 
> This seems very consistent to me. The only inconsistency is with 
> `Int.random()` covering the full width, and `Double.random()` covering only 
> `[0, 1)`, but to me this functionality is very precedented in many other 
> languages. Also by removing `Randomizable`, other data types like `Data` 
> don’t have to conform to a protocol, but can just add a random initializer 
> that fits its needs.
> 
> I think now is when people will start saying, “Int.random() bad, modulo bias, 
> no no” x)
> I see the potential for error here, but logically I’m thinking that so many 
> other languages have this feature and I wonder if you think they all did it 
> wrong too and shouldn’t have done so. This type of behavior is found in C, 
> C++, C#, Java, etc. I agree with Jonathon in that maybe we could suggest a 
> warning/fixit in Xcode.
> 
> tl;dr - Remove `Randomizable`, remove associated type on 
> `RandomNumberGenerator`, be consistent with `.random()` with other properties 
> and functions with every collection, preserve static `random()` and 
> `random(in:)` syntax.

I would co-sign all of this except for preserving Int.random() and 
Double.random(), for the reasons I’ve laid out before, those Xiaodi responded 
with, and even the ergonomics of writing and reading code:

- For floating-point values, if someone wants a [0, 1) range, I see no problem 
with having them write `Double.random(in: 0..<1)`. That’s still nice and short, 
and there’s no question about what kind of val

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

2018-01-11 Thread Xiaodi Wu via swift-evolution
On Thu, Jan 11, 2018 at 9:17 PM, Alejandro Alonso via swift-evolution <
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.. justification for a static property on one of the Integer protocols as
> shorthand for that.” I believe this makes it perfectly justifiable for
> `.random()` on numeric types. This also creates a consistency with
> `Bool.random()` making it justifiable for this as well.
>
> We can do all of this without `Randomizable` as well! Add extension
> methods on `FixedWidthInteger`, `BinaryFloatingPoint`, and `Bool`. These
> will be the methods that crash on an empty range, but we can precondition
> here to provide helpful debugging for developers. You made reference to
> users using the range based api for a safe alternative if they needed
> optionals.
>
> ```
> // Here you can use something more runtime oriented (such as an array
> count)
> guard let x = (0 ..< 5).random() else {
> fatalError(“not going to happen")
> }
> ```
>
> I’m not too sure if you’ve had a change of heart, but I think the
> following is justifiable if we remove `Randomizable`.
>
> Sample Syntax:
> ```
> // Full Int width (shorthand for Int.random(in: .min … .max))
> Int.random()
>
> // random int from [0, 10)
> Int.random(in: 0 ..< 10)
>
> // random double from [0, 1) (Modulo isn’t an issue here!)
> Double.random()
>
> // random double from [0, .pi)
> Double.random(in: 0 ..< .pi)
>
> // random boolean
> Bool.random()
> ```
>
> This seems very consistent to me. The only inconsistency is with
> `Int.random()` covering the full width, and `Double.random()` covering only
> `[0, 1)`, but to me this functionality is very precedented in many other
> languages. Also by removing `Randomizable`, other data types like `Data`
> don’t have to conform to a protocol, but can just add a random initializer
> that fits its needs.
>
> I think now is when people will start saying, “Int.random() bad, modulo
> bias, no no” x)
> I see the potential for error here, but logically I’m thinking that so
> many other languages have this feature and I wonder if you think they all
> did it wrong too and shouldn’t have done so.
>

You will have noted, surely, the evidence given above that in Apple's
internal code the majority of uses of APIs equivalent to `Int.random()` are
erroneous due to unintended modulo bias. Yes, what that would imply is that
all the other languages did it wrong. Why do you feel it is so important to
have a shorthand that enables no additional behavior in the face of
overwhelming evidence that it is actively harmful?

Likewise, you acknowledge the inconsistency of Int.random() and
Double.random(), yet again suggest a shorthand that enables no additional
behavior in spite of the potential for misunderstanding. What advantage of
having such an API do you see which could overcome this very glaring
drawback?

This type of behavior is found in C, C++, C#, Java, etc. I agree with
> Jonathon in that may

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 
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 
mailto:swift-evolution@swift.org>> wrote:


On Dec 2, 2017, at 6:02 PM, Xiaodi Wu via swift-evolution 
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 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 autoc

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 so I don’t 
always have to 

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

2018-01-11 Thread Letanyan Arumugam via swift-evolution
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 so I 
> don’t always have to switch on the enum in other code that deals with this. I 
> just ask for the bounds or constrained T (Note: T here refers to the type for 
> a single axis as opposed to the generated t

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

2018-01-11 Thread Jonathan Hull via swift-evolution

> On Jan 10, 2018, at 4:42 PM, Nate Cook  wrote:
> 
> I don’t see how a single distribution would generate both integers and 
> colors. Can your color type be initialized from an integer? Since the 
> “distributions” in that playground are just sequences, you could add 
> .lazy.map({ Color(value: $0) }) to transform an integer-producing 
> distribution into a color-producing one. (Which is pretty cool, tbh.)

See my other email for details, but it is essentially initialized from a 
sequence of 2-4 UInt* (one for each axis).  I usually fix all but one dimension 
for aesthetic reasons though, so yes-ish**.

Thanks,
Jon

* I do mean UInt, and not UInt32 or UInt64. The amount of randomness it grabs 
is based on the word size of the platform, since CGFloats are as well.

** It currently naively still burns 2-4 UInt worth of randomness even if the 
axises are fixed, but it is ignoring 1-3 of the numbers in that case and only 
really using 1.  I could easily optimize this without changing the interface 
though.___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2018-01-11 Thread Jonathan Hull via swift-evolution

> On Jan 10, 2018, at 4:42 PM, Nate Cook  wrote:
>> Right. I guess my thought is that I would like them to be able to use a 
>> standard creation pattern so it doesn’t vary from type to type (that is the 
>> whole point of “unification” in my mind).  In my own code, I have a concept 
>> of constraint, of which a set are passed to the object being created. This 
>> allows me to random create colors which look good together, etc….  I then 
>> have some convenience methods which just automatically create an appropriate 
>> constraint from a range where appropriate.  I’d really like to see something 
>> standard which allows for constraints other than simple ranges.
> 
> Is it possible for you to share some of this code?

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 so I 
don’t always have to switch on the enum in other 

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

2018-01-10 Thread Nevin Brackett-Rozinsky via swift-evolution
On Wed, Jan 10, 2018 at 6:02 PM, Jens Persson via swift-evolution <
swift-evolution@swift.org> wrote:

> I agree.
>
> If there should be an API to produce a random Double without parameters
> then IMHO it should simply be a uniformly distributed Double in the unit
> range [0, 1). Very useful as a basic building block and can be constructed
> very fast from a random bitpattern like eg:
> extension Double {
> init(unitRange v: UInt64) {
> self = Double(v >> Double.exponentBitCount) * (.ulpOfOne/2.0)
> }
> }
>

The implementation of randomness for floating point types deserves in-depth
consideration. I know that we have some IEEE-754 experts on this list, and
it would be great to have them weigh in. For instance…

When generating a uniformly-distributed floating point number in a
half-open range with finite bounds, should every representable value in
that range be possible to produce? If so, should each representable value v
appear with probability proportional to (v.nextUp - v), which may be
different from (x.ulp)?

In other words, conceptually, should the API behave as if a real number
were chosen uniformly from the range, then rounded down to the closest
representable value that does not exceed it?

Or should some fixed number of equally-spaced values that span the range be
the only possible results?

Or something else?

Should subnormal values be producible?

There is no uniform distribution over an infinite-length continuum, so how
should infinite ranges be handled? In the range (0.0 ..< .infinity) should
we always return .greatestFiniteMagnitude? And in (-.infinity ..< 0.0)
should we always return (-.infinity)? What about (-.infinity ..<
.infinity)? Should there be preconditions that can fail at runtime, or
should we sometime return .nan, or what?

• • •

These are just a few of the questions that spring to mind, so I think it is
highly important that floating-point randomness gets sufficient attention
to ensure that we land on a well-considered design.

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


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

2018-01-10 Thread Nate Cook via swift-evolution
> On Jan 9, 2018, at 3:07 PM, Jonathan Hull  wrote:
> 
>> 
>> On Jan 9, 2018, at 8:28 AM, Nate Cook > > wrote:
>> 
>>> On Jan 9, 2018, at 4:12 AM, Jonathan Hull >> > wrote:
>>> 
>>> Some thoughts:
>>> 
>>> - How do I randomly select an enum?
>> 
>> Vote for SE-0194! :)
>> 
>>> - I like that RandomNumberGenerator doesn’t have an associated type. I 
>>> agree that we should just spit out UInt64s for simplicity.
>> 
>> It simplifies things a lot, at some performance cost. For example, the LCRNG 
>> type really produces UInt32s, so I have to use two of its outputs to 
>> generate one value, even if I don’t need that many bits.
> 
> I agree with you, but just to play devil’s advocate, why not have two 
> outputs: one for UInt32 and another for UInt64?  The generator itself would 
> only have to provide one of the UInt types and the other would be provided by 
> default implementation (either by stacking 2 UInt32s or discarding half of a 
> UInt64).  I know this is less minimal, but I don’t think it is actually 
> complicated or hard to use. You just ask for the type that is most useful for 
> you.

That should work fine. The savings would depend on whether the algorithms using 
random generators would use the smaller size when necessary.

>>> - I don’t like how it is so closely tied with Range.  I realize that both 
>>> Int and Float work with Ranges, but other random types do not (e.g. 
>>> CGVectors).  You are special casing FixedWidthInteger and 
>>> BinaryFloatingPoint, which are very important… but we lose the ability to 
>>> deal with other randomly generated types.
>>> 
>>> - Following on the previous point, I don’t like that the code for dealing 
>>> with Integers/Floats is in Range.  It feels like things aren’t properly 
>>> encapsulated. 
>> 
>> I actually agree with you, and for getting individual values prefer the form 
>> `let x = Int.random(in: 1…10)`. Here’s how I got to what’s in the playground:
>> 
>> 1) We definitely want to be able to select a random element from a 
>> collection.
>> 2) Given that, we’ll have (1…10).random() and (0..<10).random() even if 
>> those aren’t what we prefer, and people will use them.
>> 3) If people use that construction for integers, it will be strange to not 
>> have the same facility for floating-point numbers.
>> 4) Once we have the range-based capability for both, the type-based versions 
>> are redundant (i.e., they can be added in the future if we decide we made 
>> the wrong decision by excluding them).
>> 
>> You’re of course correct that a pattern of range-based random functions 
>> doesn’t extend well to other types. I show on the last page a couple 
>> different ways of writing those, for Bool and Data. Most of the other types 
>> you’d want to create lie outside the Swift standard library, so we can’t 
>> address really those here.
> 
> Right. I guess my thought is that I would like them to be able to use a 
> standard creation pattern so it doesn’t vary from type to type (that is the 
> whole point of “unification” in my mind).  In my own code, I have a concept 
> of constraint, of which a set are passed to the object being created. This 
> allows me to random create colors which look good together, etc….  I then 
> have some convenience methods which just automatically create an appropriate 
> constraint from a range where appropriate.  I’d really like to see something 
> standard which allows for constraints other than simple ranges.

Is it possible for you to share some of this code?

> I think I would feel at least a little better if the range stuff worked for 
> any type which can be put in a range…
> 
> I also feel like the focus on ranges to the exclusion of everything else is 
> one of those cute things that will come back to bite us later.  My main focus 
> is on random things which are presented to the user in some way, and I 
> realize that is a different use-case than most programmers. Even for things 
> like pure number generation, I am worried about things like sig-figs and not 
> just range.
> 
>>> - Why bother supporting non-closed Ranges at all?  If you only allow closed 
>>> ranges, then you can’t end up with an empty range. The only difference in 
>>> behavior I can think of is on floating point, but I can’t think of a 
>>> use-case where excluding the supremum is actually useful in any real world 
>>> way.
>> 
>> Half-open ranges are a major use case for generating random numbers, 
>> particularly when working with collections. Whenever you see that someone’s 
>> written `random() % n`, that’s the half-open range 0.. 
> Ok, you convinced me on the half-open ranges.
> 
> I still think the best way to handle the 'random() % n' issue is to look for 
> it as a pattern and then just issue a warning/fixit.
> 
>>> - This may sound strange, but I would really like to see Bool handled as a 
>>> default implementation on the generator protocol itself.  On my own version 
>>> of this I have b

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

2018-01-10 Thread Mike Kluev via swift-evolution
on Thu, 11 Jan 2018 00:02:18 +0100 Jens Persson  wrote:

If there should be an API to produce a random Double without parameters
> then IMHO it should simply be a uniformly distributed Double in the unit
> range [0, 1). Very useful as a basic building block...


[0..1) sounds reasonable. even if disregard +/- zeroes, infinities, NAN's,
etc., uniform distribution between Double.min ... Double.max makes little
sense.

and it shall be relatively easy to bit cast UInt64 to Double for those who
want to test various double patterns (e.g. for testing).

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


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

2018-01-10 Thread Jens Persson via swift-evolution
I agree.

If there should be an API to produce a random Double without parameters
then IMHO it should simply be a uniformly distributed Double in the unit
range [0, 1). Very useful as a basic building block and can be constructed
very fast from a random bitpattern like eg:
extension Double {
init(unitRange v: UInt64) {
self = Double(v >> Double.exponentBitCount) * (.ulpOfOne/2.0)
}
}



On Wed, Jan 10, 2018 at 11:48 PM, Saagar Jha  wrote:

> Which begs the question: why would you want to do something like this?
> Creating a “random” Double from its full range of values is an odd thing to
> do, and the fact that it is non-uniform and has irregularities like
> infinity and signed zeros makes it likely that any such usage is probably
> done in error (the one reason I can think of is if you’re trying to test
> your code with random Doubles, but I’d argue for keeping NaN in that case).
> Generally users are looking for uniform distributions or ones that follow
> some set pattern (e.g. normal, Bernoulli), so this doesn’t seem useful at
> all.
>
> Saagar Jha
>
> On Jan 10, 2018, at 14:39, Jens Persson  wrote:
>
> On Wed, Jan 10, 2018 at 11:27 PM, Saagar Jha  wrote:
>
>> Not a floating point expert, but are you sure this works? I have a
>> feeling this would lead to a distribution that’s not uniform.
>>
>>
> Yes, it would not be uniform, which is exactly what I meant by the last
> part of: "Assuming you are ok with signed zero and infinities and
> "strange" bias as result of IEEE 754"
>
> Also, I think it's impossible to get a uniform distribution of all non-Nan
> Double values (since they include +- infinity).
>
> /Jens
>
>
>
>> Saagar Jha
>>
>> On Jan 10, 2018, at 14:07, Jens Persson via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>> On Tue, Jan 9, 2018 at 10:07 PM, Jonathan Hull via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>>>
>>> One additional question.  How do you ergonomically get a Double which
>>> doesn’t have a range, but also isn’t NaN?
>>>
>>>
>> Assuming you are ok with signed zero and infinities and "strange" bias as
>> result of IEEE 754:
>>
>> func randomNonNanDouble(using generator: R) ->
>> Double {
>> while true {
>> let rndUInt64 = generator.next()
>> let rndDouble = Double(bitPattern: rndUInt64)
>> if rndDouble != Double.nan { return rndDouble }
>> }
>> }
>>
>> /Jens
>>
>> ___
>> 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

2018-01-10 Thread Saagar Jha via swift-evolution
Which begs the question: why would you want to do something like this? Creating 
a “random” Double from its full range of values is an odd thing to do, and the 
fact that it is non-uniform and has irregularities like infinity and signed 
zeros makes it likely that any such usage is probably done in error (the one 
reason I can think of is if you’re trying to test your code with random 
Doubles, but I’d argue for keeping NaN in that case). Generally users are 
looking for uniform distributions or ones that follow some set pattern (e.g. 
normal, Bernoulli), so this doesn’t seem useful at all.

Saagar Jha

> On Jan 10, 2018, at 14:39, Jens Persson  wrote:
> 
> On Wed, Jan 10, 2018 at 11:27 PM, Saagar Jha  > wrote:
> Not a floating point expert, but are you sure this works? I have a feeling 
> this would lead to a distribution that’s not uniform.
> 
> 
> Yes, it would not be uniform, which is exactly what I meant by the last part 
> of: "Assuming you are ok with signed zero and infinities and "strange" bias 
> as result of IEEE 754"
> 
> Also, I think it's impossible to get a uniform distribution of all non-Nan 
> Double values (since they include +- infinity).
> 
> /Jens
> 
>  
> Saagar Jha
> 
>> On Jan 10, 2018, at 14:07, Jens Persson via swift-evolution 
>> mailto:swift-evolution@swift.org>> wrote:
>> 
>> On Tue, Jan 9, 2018 at 10:07 PM, Jonathan Hull via swift-evolution 
>> mailto:swift-evolution@swift.org>> wrote:
>> 
>> One additional question.  How do you ergonomically get a Double which 
>> doesn’t have a range, but also isn’t NaN?
>> 
>> 
>> Assuming you are ok with signed zero and infinities and "strange" bias as 
>> result of IEEE 754:
>> 
>> func randomNonNanDouble(using generator: R) -> 
>> Double {
>> while true {
>> let rndUInt64 = generator.next()
>> let rndDouble = Double(bitPattern: rndUInt64)
>> if rndDouble != Double.nan { return rndDouble }
>> }
>> }
>> 
>> /Jens
>> 
>> ___
>> 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

2018-01-10 Thread Jens Persson via swift-evolution
On Wed, Jan 10, 2018 at 11:27 PM, Saagar Jha  wrote:

> Not a floating point expert, but are you sure this works? I have a feeling
> this would lead to a distribution that’s not uniform.
>
>
Yes, it would not be uniform, which is exactly what I meant by the last
part of: "Assuming you are ok with signed zero and infinities and "strange"
bias as result of IEEE 754"

Also, I think it's impossible to get a uniform distribution of all non-Nan
Double values (since they include +- infinity).

/Jens



> Saagar Jha
>
> On Jan 10, 2018, at 14:07, Jens Persson via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> On Tue, Jan 9, 2018 at 10:07 PM, Jonathan Hull via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>>
>> One additional question.  How do you ergonomically get a Double which
>> doesn’t have a range, but also isn’t NaN?
>>
>>
> Assuming you are ok with signed zero and infinities and "strange" bias as
> result of IEEE 754:
>
> func randomNonNanDouble(using generator: R) ->
> Double {
> while true {
> let rndUInt64 = generator.next()
> let rndDouble = Double(bitPattern: rndUInt64)
> if rndDouble != Double.nan { return rndDouble }
> }
> }
>
> /Jens
>
> ___
> 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

2018-01-10 Thread Saagar Jha via swift-evolution
Not a floating point expert, but are you sure this works? I have a feeling this 
would lead to a distribution that’s not uniform.

Saagar Jha

> On Jan 10, 2018, at 14:07, Jens Persson via swift-evolution 
>  wrote:
> 
> On Tue, Jan 9, 2018 at 10:07 PM, Jonathan Hull via swift-evolution 
> mailto:swift-evolution@swift.org>> wrote:
> 
> One additional question.  How do you ergonomically get a Double which doesn’t 
> have a range, but also isn’t NaN?
> 
> 
> Assuming you are ok with signed zero and infinities and "strange" bias as 
> result of IEEE 754:
> 
> func randomNonNanDouble(using generator: R) -> 
> Double {
> while true {
> let rndUInt64 = generator.next()
> let rndDouble = Double(bitPattern: rndUInt64)
> if rndDouble != Double.nan { return rndDouble }
> }
> }
> 
> /Jens
> 
> ___
> 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

2018-01-10 Thread Jens Persson via swift-evolution
On Tue, Jan 9, 2018 at 10:07 PM, Jonathan Hull via swift-evolution <
swift-evolution@swift.org> wrote:

>
> One additional question.  How do you ergonomically get a Double which
> doesn’t have a range, but also isn’t NaN?
>
>
Assuming you are ok with signed zero and infinities and "strange" bias as
result of IEEE 754:

func randomNonNanDouble(using generator: R) ->
Double {
while true {
let rndUInt64 = generator.next()
let rndDouble = Double(bitPattern: rndUInt64)
if rndDouble != Double.nan { return rndDouble }
}
}

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


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

2018-01-09 Thread Kelvin Ma via swift-evolution
On Tue, Jan 9, 2018 at 5:12 AM, Jonathan Hull via swift-evolution <
swift-evolution@swift.org> wrote:

> Some thoughts:
>
> - How do I randomly select an enum?
>

carefully, of course


>
> - I like that RandomNumberGenerator doesn’t have an associated type. I
> agree that we should just spit out UInt64s for simplicity.
>
> - I don’t like how it is so closely tied with Range.  I realize that both
> Int and Float work with Ranges, but other random types do not (e.g.
> CGVectors).  You are special casing FixedWidthInteger and
> BinaryFloatingPoint, which are very important… but we lose the ability to
> deal with other randomly generated types.
>

generating “random vectors” is a *big* mood and it’s not as simple as
varying on a range of *R*3. There’s a mild but non-trivial amount of work
needed to get a uniform distribution and avoid degeneracies and division by
zero. and “random” can mean different things, sometimes you want a random
2D disk of vectors that all live in some plane in 3D space because you need
them to be perpendicular to something. And at any rate, CGVector is not a
standard type, while Int and Float are.


>
> - Following on the previous point, I don’t like that the code for dealing
> with Integers/Floats is in Range.  It feels like things aren’t properly
> encapsulated.
>
> - Why bother supporting non-closed Ranges at all?  If you only allow
> closed ranges, then you can’t end up with an empty range. The only
> difference in behavior I can think of is on floating point, but I can’t
> think of a use-case where excluding the supremum is actually useful in any
> real world way.
>

i see this as an inconvenience for the sake of security theater. Usually
when you want a random integer on a continuous range, you’re using them as
indices into something. And indices go from 0 ..< count, not 0 ... (count -
1). if whatever you’re indexing into is empty, it’s empty.


>
> - This may sound strange, but I would *really* like to see Bool handled
> as a default implementation on the generator protocol itself.  On my own
> version of this I have both the ‘coinFlip()’ and ‘oneIn(_ num:Int)’ methods
> which I find extremely useful.  CoinFlip just gives you a random bool,
> whereas you can say things like oneIn(100) to get ‘true’ roughly 1 out of
> every 100 times you call it.  These are useful for branching randomly.
> They are most useful on the source/generator itself because it is ergonomic
> when you need to rewind the source.
>
> - IMO distributions should be sources/generators themselves which just
> wrap another source.  We could have a subprotocol of RandomNumberGenerator
> which just semantically guarantees uniform distribution, and then
> distributions that need it could be sure of the input distribution.  Notice
> this doesn’t limit the distribution to only be used for Integers as they
> are in the demo. They can be used anywhere a source can be used.
>
> - Having a subprotocol for generators which can be rewound is extremely
> important for entire classes of real-world problems.  I have spent a lot of
> time using this and it solves a LOT of problems. For example, I have a
> Lorem Ipsum Generator which takes Attributes and a CGSize to fill.  It
> works by branching (using the Bool methods above) and then rewinding bits
> which don’t fit (If you just futz with the last part instead of generating
> appropriate clauses, it won’t look right).  I also have a bunch of
> backtracking algorithms which rely on this rewind ability.  Plus numerous
> visual effects which rely on a repeatable rewindable source.
> *- Tl;dr: It isn’t enough to just have a seed, you need to be able to mark
> a state of a generator and return to that state later.*
>
> My RepeatableRandomSource Protocol has 3 extra methods:
> - It takes a seed
> - It has a mark() method which returns a token
> - It has a returnToMark(_ mark:Mark) method which takes a token and
> restores the appropriate state
>
> - I really appreciate that you made a playground :-)
>
> Thanks,
> Jon
>
>
> On Jan 8, 2018, at 11:02 AM, Nate Cook via swift-evolution <
> 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 

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

2018-01-09 Thread Jonathan Hull via swift-evolution

> On Jan 9, 2018, at 8:28 AM, Nate Cook  wrote:
> 
>> On Jan 9, 2018, at 4:12 AM, Jonathan Hull > > wrote:
>> 
>> Some thoughts:
>> 
>> - How do I randomly select an enum?
> 
> Vote for SE-0194! :)
> 
>> - I like that RandomNumberGenerator doesn’t have an associated type. I agree 
>> that we should just spit out UInt64s for simplicity.
> 
> It simplifies things a lot, at some performance cost. For example, the LCRNG 
> type really produces UInt32s, so I have to use two of its outputs to generate 
> one value, even if I don’t need that many bits.

I agree with you, but just to play devil’s advocate, why not have two outputs: 
one for UInt32 and another for UInt64?  The generator itself would only have to 
provide one of the UInt types and the other would be provided by default 
implementation (either by stacking 2 UInt32s or discarding half of a UInt64).  
I know this is less minimal, but I don’t think it is actually complicated or 
hard to use. You just ask for the type that is most useful for you.


>> - I don’t like how it is so closely tied with Range.  I realize that both 
>> Int and Float work with Ranges, but other random types do not (e.g. 
>> CGVectors).  You are special casing FixedWidthInteger and 
>> BinaryFloatingPoint, which are very important… but we lose the ability to 
>> deal with other randomly generated types.
>> 
>> - Following on the previous point, I don’t like that the code for dealing 
>> with Integers/Floats is in Range.  It feels like things aren’t properly 
>> encapsulated. 
> 
> I actually agree with you, and for getting individual values prefer the form 
> `let x = Int.random(in: 1…10)`. Here’s how I got to what’s in the playground:
> 
> 1) We definitely want to be able to select a random element from a collection.
> 2) Given that, we’ll have (1…10).random() and (0..<10).random() even if those 
> aren’t what we prefer, and people will use them.
> 3) If people use that construction for integers, it will be strange to not 
> have the same facility for floating-point numbers.
> 4) Once we have the range-based capability for both, the type-based versions 
> are redundant (i.e., they can be added in the future if we decide we made the 
> wrong decision by excluding them).
> 
> You’re of course correct that a pattern of range-based random functions 
> doesn’t extend well to other types. I show on the last page a couple 
> different ways of writing those, for Bool and Data. Most of the other types 
> you’d want to create lie outside the Swift standard library, so we can’t 
> address really those here.

Right. I guess my thought is that I would like them to be able to use a 
standard creation pattern so it doesn’t vary from type to type (that is the 
whole point of “unification” in my mind).  In my own code, I have a concept of 
constraint, of which a set are passed to the object being created. This allows 
me to random create colors which look good together, etc….  I then have some 
convenience methods which just automatically create an appropriate constraint 
from a range where appropriate.  I’d really like to see something standard 
which allows for constraints other than simple ranges.

I think I would feel at least a little better if the range stuff worked for any 
type which can be put in a range…

I also feel like the focus on ranges to the exclusion of everything else is one 
of those cute things that will come back to bite us later.  My main focus is on 
random things which are presented to the user in some way, and I realize that 
is a different use-case than most programmers. Even for things like pure number 
generation, I am worried about things like sig-figs and not just range.

>> - Why bother supporting non-closed Ranges at all?  If you only allow closed 
>> ranges, then you can’t end up with an empty range. The only difference in 
>> behavior I can think of is on floating point, but I can’t think of a 
>> use-case where excluding the supremum is actually useful in any real world 
>> way.
> 
> Half-open ranges are a major use case for generating random numbers, 
> particularly when working with collections. Whenever you see that someone’s 
> written `random() % n`, that’s the half-open range 0..> - This may sound strange, but I would really like to see Bool handled as a 
>> default implementation on the generator protocol itself.  On my own version 
>> of this I have both the ‘coinFlip()’ and ‘oneIn(_ num:Int)’ methods which I 
>> find extremely useful.  CoinFlip just gives you a random bool, whereas you 
>> can say things like oneIn(100) to get ‘true’ roughly 1 out of every 100 
>> times you call it.  These are useful for branching randomly.  They are most 
>> useful on the source/generator itself because it is ergonomic when you need 
>> to rewind the source.
> 
> Bool is certainly a very important type to be able to randomly generate. I’m 
> not opposed to it being included in a proposal, but it’s simple enough to do 
> on your own that it didn

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

2018-01-09 Thread Dave Abrahams via swift-evolution


> On Jan 9, 2018, at 11:01 AM, Ben Cohen via swift-evolution 
>  wrote:
> 
> 
> 
>> On Jan 9, 2018, at 2:12 AM, Jonathan Hull via swift-evolution 
>> mailto:swift-evolution@swift.org>> wrote:
>> 
>> - Why bother supporting non-closed Ranges at all?  If you only allow closed 
>> ranges, then you can’t end up with an empty range. The only difference in 
>> behavior I can think of is on floating point, but I can’t think of a 
>> use-case where excluding the supremum is actually useful in any real world 
>> way.
>> 
> 
> 
> Ranges are the currency type, whereas closed ranges aren’t. We should try to 
> avoid any solution that goes against this pattern. People are going to have a 
> Range, and having to convert it into a ClosedRange just to get a random 
> number from it is confusing.
> 
> The argument goes that you want to avoid traps, therefore forbid half-open 
> range because it can be empty and might trap, whereas closed ranges doesn’t. 
> Therefore, let’s only have closed ranges. Type safety ftw. 
> 
> In practice, I don’t think this is justified. Realistically, you can divide 
> uses into two cases, literals and runtime-generated ranges.
> 
> Literals are obviously empty by inspection. It’s hard to do this by accident 
> and any kind of coverage testing of (0..<0).random() will immediately trap. 
> So probably a non-issue.
> 
> If you’re generating ranges at runtime from variables, you have another risk 
> of traps that applies just as much to closed ranges: inversion.
> 
> i.e.:
> 
> x = 5
> y = 4
> x...y // boom, can't form Range with upperBound < lowerBound
> 
> This is easily done. Nate’s example playground even had a possible case!
> 
> // better hope items always has at least 3 elements...
> let countForSale = (3...items.count).random() 
> 
> Given this is already an issue, the additional risk of trapping on empty 
> half-open ranges seems modest and acceptable to me, compared to the 
> alternative of encouraging constant banging of the result from .random() on 
> ranges.

+1


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


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

2018-01-09 Thread Ben Cohen via swift-evolution


> On Jan 9, 2018, at 2:12 AM, Jonathan Hull via swift-evolution 
>  wrote:
> 
> - Why bother supporting non-closed Ranges at all?  If you only allow closed 
> ranges, then you can’t end up with an empty range. The only difference in 
> behavior I can think of is on floating point, but I can’t think of a use-case 
> where excluding the supremum is actually useful in any real world way.
> 


Ranges are the currency type, whereas closed ranges aren’t. We should try to 
avoid any solution that goes against this pattern. People are going to have a 
Range, and having to convert it into a ClosedRange just to get a random number 
from it is confusing.

The argument goes that you want to avoid traps, therefore forbid half-open 
range because it can be empty and might trap, whereas closed ranges doesn’t. 
Therefore, let’s only have closed ranges. Type safety ftw. 

In practice, I don’t think this is justified. Realistically, you can divide 
uses into two cases, literals and runtime-generated ranges.

Literals are obviously empty by inspection. It’s hard to do this by accident 
and any kind of coverage testing of (0..<0).random() will immediately trap. So 
probably a non-issue.

If you’re generating ranges at runtime from variables, you have another risk of 
traps that applies just as much to closed ranges: inversion.

i.e.:

x = 5
y = 4
x...y // boom, can't form Range with upperBound < lowerBound

This is easily done. Nate’s example playground even had a possible case!

// better hope items always has at least 3 elements...
let countForSale = (3...items.count).random() 

Given this is already an issue, the additional risk of trapping on empty 
half-open ranges seems modest and acceptable to me, compared to the alternative 
of encouraging constant banging of the result from .random() on ranges.


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


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

2018-01-09 Thread Nate Cook via swift-evolution
> On Jan 9, 2018, at 4:12 AM, Jonathan Hull  wrote:
> 
> Some thoughts:
> 
> - How do I randomly select an enum?

Vote for SE-0194! :)

> - I like that RandomNumberGenerator doesn’t have an associated type. I agree 
> that we should just spit out UInt64s for simplicity.

It simplifies things a lot, at some performance cost. For example, the LCRNG 
type really produces UInt32s, so I have to use two of its outputs to generate 
one value, even if I don’t need that many bits.

> - I don’t like how it is so closely tied with Range.  I realize that both Int 
> and Float work with Ranges, but other random types do not (e.g. CGVectors).  
> You are special casing FixedWidthInteger and BinaryFloatingPoint, which are 
> very important… but we lose the ability to deal with other randomly generated 
> types.
> 
> - Following on the previous point, I don’t like that the code for dealing 
> with Integers/Floats is in Range.  It feels like things aren’t properly 
> encapsulated. 

I actually agree with you, and for getting individual values prefer the form 
`let x = Int.random(in: 1…10)`. Here’s how I got to what’s in the playground:

1) We definitely want to be able to select a random element from a collection.
2) Given that, we’ll have (1…10).random() and (0..<10).random() even if those 
aren’t what we prefer, and people will use them.
3) If people use that construction for integers, it will be strange to not have 
the same facility for floating-point numbers.
4) Once we have the range-based capability for both, the type-based versions 
are redundant (i.e., they can be added in the future if we decide we made the 
wrong decision by excluding them).

You’re of course correct that a pattern of range-based random functions doesn’t 
extend well to other types. I show on the last page a couple different ways of 
writing those, for Bool and Data. Most of the other types you’d want to create 
lie outside the Swift standard library, so we can’t address really those here.

> - Why bother supporting non-closed Ranges at all?  If you only allow closed 
> ranges, then you can’t end up with an empty range. The only difference in 
> behavior I can think of is on floating point, but I can’t think of a use-case 
> where excluding the supremum is actually useful in any real world way.

Half-open ranges are a major use case for generating random numbers, 
particularly when working with collections. Whenever you see that someone’s 
written `random() % n`, that’s the half-open range 0.. - This may sound strange, but I would really like to see Bool handled as a 
> default implementation on the generator protocol itself.  On my own version 
> of this I have both the ‘coinFlip()’ and ‘oneIn(_ num:Int)’ methods which I 
> find extremely useful.  CoinFlip just gives you a random bool, whereas you 
> can say things like oneIn(100) to get ‘true’ roughly 1 out of every 100 times 
> you call it.  These are useful for branching randomly.  They are most useful 
> on the source/generator itself because it is ergonomic when you need to 
> rewind the source.

Bool is certainly a very important type to be able to randomly generate. I’m 
not opposed to it being included in a proposal, but it’s simple enough to do on 
your own that it didn’t pass the “minimal” test that I was using in the 
playground. You could use something like this static method:

extension Bool {
static func random(
probability: Double = 0.5, 
using generator: RandomNumberGenerator = Random.default
) {
return (0.0 ..< 1.0).random(using: generator) < probability
}
}

I don’t think there should be any value-producing methods on generators—most 
users shouldn’t need to think about generators at all, and the ones who have a 
specific need (repeatability, rewinding, etc) should be able to use the same 
APIs as the people who aren’t thinking about them.

> - IMO distributions should be sources/generators themselves which just wrap 
> another source.  We could have a subprotocol of RandomNumberGenerator which 
> just semantically guarantees uniform distribution, and then distributions 
> that need it could be sure of the input distribution.  Notice this doesn’t 
> limit the distribution to only be used for Integers as they are in the demo. 
> They can be used anywhere a source can be used.

I’d really like to maintain a clear line between generators and distributions 
(which I don’t think we need an additional protocol for). Distributions create 
values of a specific kind of type, with a particular distribution, which 
usually isn't suitable to use as the input for another algorithm that needs 
random data. Generators just pump out (hopefully) uniformly distributed bits, 
which distributions and other algorithms can then interpret and shape.

> - Having a subprotocol for generators which can be rewound is extremely 
> important for entire classes of real-world problems.  I have spent a lot of 
> time using this and it solves

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

2018-01-09 Thread Dave DeLong via swift-evolution


> On Jan 9, 2018, at 3:12 AM, Jonathan Hull via swift-evolution 
>  wrote:
> 
> Some thoughts:
> 
> - How do I randomly select an enum?

Well… combine this with SE-0194 and you have all the basics you need: the set 
of all enum values in a collection, and a way to pick a random element from a 
collection...

> 
> - I like that RandomNumberGenerator doesn’t have an associated type. I agree 
> that we should just spit out UInt64s for simplicity.
> 
> - I don’t like how it is so closely tied with Range.  I realize that both Int 
> and Float work with Ranges, but other random types do not (e.g. CGVectors).  
> You are special casing FixedWidthInteger and BinaryFloatingPoint, which are 
> very important… but we lose the ability to deal with other randomly generated 
> types.
> 
> - Following on the previous point, I don’t like that the code for dealing 
> with Integers/Floats is in Range.  It feels like things aren’t properly 
> encapsulated. 
> 
> - Why bother supporting non-closed Ranges at all?  If you only allow closed 
> ranges, then you can’t end up with an empty range. The only difference in 
> behavior I can think of is on floating point, but I can’t think of a use-case 
> where excluding the supremum is actually useful in any real world way.
> 
> - This may sound strange, but I would really like to see Bool handled as a 
> default implementation on the generator protocol itself.  On my own version 
> of this I have both the ‘coinFlip()’ and ‘oneIn(_ num:Int)’ methods which I 
> find extremely useful.  CoinFlip just gives you a random bool, whereas you 
> can say things like oneIn(100) to get ‘true’ roughly 1 out of every 100 times 
> you call it.  These are useful for branching randomly.  They are most useful 
> on the source/generator itself because it is ergonomic when you need to 
> rewind the source.
> 
> - IMO distributions should be sources/generators themselves which just wrap 
> another source.  We could have a subprotocol of RandomNumberGenerator which 
> just semantically guarantees uniform distribution, and then distributions 
> that need it could be sure of the input distribution.  Notice this doesn’t 
> limit the distribution to only be used for Integers as they are in the demo. 
> They can be used anywhere a source can be used.
> 
> - Having a subprotocol for generators which can be rewound is extremely 
> important for entire classes of real-world problems.  I have spent a lot of 
> time using this and it solves a LOT of problems. For example, I have a Lorem 
> Ipsum Generator which takes Attributes and a CGSize to fill.  It works by 
> branching (using the Bool methods above) and then rewinding bits which don’t 
> fit (If you just futz with the last part instead of generating appropriate 
> clauses, it won’t look right).  I also have a bunch of backtracking 
> algorithms which rely on this rewind ability.  Plus numerous visual effects 
> which rely on a repeatable rewindable source.
>   - Tl;dr: It isn’t enough to just have a seed, you need to be able to 
> mark a state of a generator and return to that state later.
> 
>   My RepeatableRandomSource Protocol has 3 extra methods:
>   - It takes a seed
>   - It has a mark() method which returns a token
>   - It has a returnToMark(_ mark:Mark) method which takes a token and 
> restores the appropriate state 
> 
> - I really appreciate that you made a playground :-)
> 
> Thanks,
> Jon
> 
> 
>> On Jan 8, 2018, at 11:02 AM, Nate Cook via swift-evolution 
>> 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 
>>> 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/n

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

2018-01-09 Thread Xiaodi Wu via swift-evolution
On Tue, Jan 9, 2018 at 05:12 Jonathan Hull via swift-evolution <
swift-evolution@swift.org> wrote:

> Some thoughts:
>
> - How do I randomly select an enum?
>
> - I like that RandomNumberGenerator doesn’t have an associated type. I
> agree that we should just spit out UInt64s for simplicity.
>
> - I don’t like how it is so closely tied with Range.  I realize that both
> Int and Float work with Ranges, but other random types do not (e.g.
> CGVectors).  You are special casing FixedWidthInteger and
> BinaryFloatingPoint, which are very important… but we lose the ability to
> deal with other randomly generated types.
>

So, I’ll defend this design. At some point, you need to expose the
primitive operation, which is the selection of a random *number* within a
range, and after our very lengthy discussions, this is the best spelling in
Swift by consensus.

- Following on the previous point, I don’t like that the code for dealing
> with Integers/Floats is in Range.  It feels like things aren’t properly
> encapsulated.
>
> - Why bother supporting non-closed Ranges at all?  If you only allow
> closed ranges, then you can’t end up with an empty range. The only
> difference in behavior I can think of is on floating point, but I can’t
> think of a use-case where excluding the supremum is actually useful in any
> real world way.
>

This is a nontrivial thing to get right; in fact, in C++, many
implementations of the standard library got it wrong for quite some time.
Additionally, generating a value in 0..<1 is a primitive operation which is
equivalent, essentially, to generating a random significand, so it is
important to expose this functionality in the standard library.

- This may sound strange, but I would *really* like to see Bool handled as
> a default implementation on the generator protocol itself.  On my own
> version of this I have both the ‘coinFlip()’ and ‘oneIn(_ num:Int)’ methods
> which I find extremely useful.  CoinFlip just gives you a random bool,
> whereas you can say things like oneIn(100) to get ‘true’ roughly 1 out of
> every 100 times you call it.  These are useful for branching randomly.
> They are most useful on the source/generator itself because it is ergonomic
> when you need to rewind the source.
>

This is a Bernoulli distribution. Which is a trivial distribution to
implement—if you have a primitive that gives you a random value in the
range 0..<1! (See, this is why you need that as a primitive.) Then, for
example, a fair coin is obtained by binning 0..<0.5 as heads and 0.5..<1 as
tails. Adjust to taste for your desired value of p.

However, more below on distributions.

- IMO distributions should be sources/generators themselves which just wrap
> another source.  We could have a subprotocol of RandomNumberGenerator which
> just semantically guarantees uniform distribution, and then distributions
> that need it could be sure of the input distribution.  Notice this doesn’t
> limit the distribution to only be used for Integers as they are in the
> demo. They can be used anywhere a source can be used.
>

One of the major critiques of the C++ design is its overcomplicated design,
one aspect of which is this wrapping of sources. Some people might like it
or find it to be their preferred design, but given that there’s some
consensus that the uniform distribution is all we’re offering in the
standard library (with everything else being more appropriate for a
third-party library that’s more elaborate), this is a design decision that
each such third-party library can decide for itself.

- Having a subprotocol for generators which can be rewound is extremely
> important for entire classes of real-world problems.  I have spent a lot of
> time using this and it solves a LOT of problems. For example, I have a
> Lorem Ipsum Generator which takes Attributes and a CGSize to fill.  It
> works by branching (using the Bool methods above) and then rewinding bits
> which don’t fit (If you just futz with the last part instead of generating
> appropriate clauses, it won’t look right).  I also have a bunch of
> backtracking algorithms which rely on this rewind ability.  Plus numerous
> visual effects which rely on a repeatable rewindable source.
> *- Tl;dr: It isn’t enough to just have a seed, you need to be able to mark
> a state of a generator and return to that state later.*
>
> My RepeatableRandomSource Protocol has 3 extra methods:
> - It takes a seed
> - It has a mark() method which returns a token
> - It has a returnToMark(_ mark:Mark) method which takes a token and
> restores the appropriate state
>

This too is one of those features that, given how we’re not offering any
such RNGs in the standard library, can be a decision for custom libraries
to design in a way that most suits themselves. Many RNGs can be seeded and
reseeded, but not all can be rewound or skipped ahead, so it’s something
where the ultimate hierarchy of protocols and their methods will depend on
the concrete types on offer.

- I really ap

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

2018-01-09 Thread Jonathan Hull via swift-evolution
Some thoughts:

- How do I randomly select an enum?

- I like that RandomNumberGenerator doesn’t have an associated type. I agree 
that we should just spit out UInt64s for simplicity.

- I don’t like how it is so closely tied with Range.  I realize that both Int 
and Float work with Ranges, but other random types do not (e.g. CGVectors).  
You are special casing FixedWidthInteger and BinaryFloatingPoint, which are 
very important… but we lose the ability to deal with other randomly generated 
types.

- Following on the previous point, I don’t like that the code for dealing with 
Integers/Floats is in Range.  It feels like things aren’t properly 
encapsulated. 

- Why bother supporting non-closed Ranges at all?  If you only allow closed 
ranges, then you can’t end up with an empty range. The only difference in 
behavior I can think of is on floating point, but I can’t think of a use-case 
where excluding the supremum is actually useful in any real world way.

- This may sound strange, but I would really like to see Bool handled as a 
default implementation on the generator protocol itself.  On my own version of 
this I have both the ‘coinFlip()’ and ‘oneIn(_ num:Int)’ methods which I find 
extremely useful.  CoinFlip just gives you a random bool, whereas you can say 
things like oneIn(100) to get ‘true’ roughly 1 out of every 100 times you call 
it.  These are useful for branching randomly.  They are most useful on the 
source/generator itself because it is ergonomic when you need to rewind the 
source.

- IMO distributions should be sources/generators themselves which just wrap 
another source.  We could have a subprotocol of RandomNumberGenerator which 
just semantically guarantees uniform distribution, and then distributions that 
need it could be sure of the input distribution.  Notice this doesn’t limit the 
distribution to only be used for Integers as they are in the demo. They can be 
used anywhere a source can be used.

- Having a subprotocol for generators which can be rewound is extremely 
important for entire classes of real-world problems.  I have spent a lot of 
time using this and it solves a LOT of problems. For example, I have a Lorem 
Ipsum Generator which takes Attributes and a CGSize to fill.  It works by 
branching (using the Bool methods above) and then rewinding bits which don’t 
fit (If you just futz with the last part instead of generating appropriate 
clauses, it won’t look right).  I also have a bunch of backtracking algorithms 
which rely on this rewind ability.  Plus numerous visual effects which rely on 
a repeatable rewindable source.
- Tl;dr: It isn’t enough to just have a seed, you need to be able to 
mark a state of a generator and return to that state later.

My RepeatableRandomSource Protocol has 3 extra methods:
- It takes a seed
- It has a mark() method which returns a token
- It has a returnToMark(_ mark:Mark) method which takes a token and 
restores the appropriate state 

- I really appreciate that you made a playground :-)

Thanks,
Jon


> On Jan 8, 2018, at 11:02 AM, 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 
>> 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 standar

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

2018-01-08 Thread Xiaodi Wu via swift-evolution
Agreed. This simplification is more or less precisely the shape of the
proposal that I was hoping for.

I'm worried that "optional" `random()` and "non-optional" `random()` are
spelled the same way, especially as the type is not always obvious when,
say, a range or collection is referred to by variable name and not as a
literal. And I do think that may become even more problematic should we
decide that some ranges (i.e., the countable ones) ought to conform to
Collection. (But more on that later.)

But besides that concern (which, I would hope, should not be glossed over),
I do like the direction of Nate's playground.


On Mon, Jan 8, 2018 at 5:37 PM, David Hart via swift-evolution <
swift-evolution@swift.org> wrote:

> Unfortunately, it wasn’t my only worry. The simplifications from dropping
> Randomizable and random(in: ) are also very welcome for me.
>
>
> On 8 Jan 2018, at 23:08, Alejandro Alonso  wrote:
>
> 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 <
> swift-evolution@swift.org> 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 <
> 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> 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> wrote:
>
>
> On Dec 2, 2017, at 6:02 PM, Xiaodi Wu via swift-evolution <
> 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 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.

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

2018-01-08 Thread David Hart via swift-evolution
Unfortunately, it wasn’t my only worry. The simplifications from dropping 
Randomizable and random(in: ) are also very welcome for me.

> On 8 Jan 2018, at 23:08, Alejandro Alonso  wrote:
> 
> 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 
> mailto:swift-evolution@swift.org>> 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 
>>> 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 
 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 
 mailto:swift-evolution@swift.org>> wrote:
 
> 
>> On Dec 2, 2017, at 6:02 PM, Xiaodi Wu via swift-evolution 
>> 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 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 cre

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

2018-01-08 Thread Letanyan Arumugam via swift-evolution

> On 08 Jan 2018, at 21: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


+1 to this design

Just my 2 cents but this looks very simple and easy to use due to being very 
consistent. I also like that Randomizable was dropped as I feel it doesn’t hold 
its weight.___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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 
mailto:swift-evolution@swift.org>> 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 
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 
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 
mailto:swift-evolution@swift.org>> wrote:


On Dec 2, 2017, at 6:02 PM, Xiaodi Wu via swift-evolution 
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 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
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

___

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

2018-01-08 Thread David Hart via swift-evolution
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 
>> 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 
>> mailto:swift-evolution@swift.org>> wrote:
>> 
>>> 
 On Dec 2, 2017, at 6:02 PM, Xiaodi Wu via swift-evolution 
 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 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 mail

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

2018-01-02 Thread Xiaodi Wu via swift-evolution
On Tue, Jan 2, 2018 at 10:19 AM, Dave DeLong via swift-evolution <
swift-evolution@swift.org> wrote:

> Just skimmed through the updated proposal and am weighing in with my naïve
> opinions:
>
>
>- I’m still highly skeptical of a static “T.random” API. I’ve yet to
>see a convincing example where it’d be useful to pick a value from the
>range of all possible values. The only truly useful one I’ve seen is “pick
>a random bool”, which could easily be done via “[true, false].random()"
>
>- I much prefer the GameplayKit API[0], which breaks the idea of
>randomness up in to 2 separate concepts:
>   - A “Source” → Where the random numbers come from
>   - A “Distribution” → Initialized with a source, it makes sure the
>   produced numbers exhibit a specific distribution over multiple 
> samplings.
>   Ie, a uniform distribution vs a Gaussian distribution, or something 
> like “I
>   want to pick a card from a deck but bias choices towards Spades or 
> Aces”.
>   I’m also reminded of the anecdote of how iTunes had to modify their
>   “playlist shuffle” algorithm to be less random[1], because the true
>   randomness would do weird things that made it seem not random. Spotify 
> had
>   the same problem and solution[2].
>   - Breaking things up like this would also make it easier to test
>   randomness (by using a replay-able source) but that still follow the
>   parameters of your app (that it has a bell-curve distribution of
>   probabilities, for example)
>
>   - I’d still really really really like to see how this could be done
>as two separate things:
>   - A minimal implementation in the Standard Library (like, defining
>   the base Source and Distribution protocols, with a single default
>   implementation of each)
>   - A proposal for a more complete “non-standard library” where the
>   larger array of functionality would be contained. For example, IMO I 
> don’t
>   think the shuffling stuff needs to be in the standard library. This is 
> also
>   where all the cryptographically secure stuff (that your typical app
>   developer does not need) would live.
>
>   - The “random” element of a collection/range should be “func
>random() → Element?”, not “var random: Element?”. Property values shouldn't
>change between accesses. Ditto the static “Randomizable.random” property.
>
>- What do you think about actively discouraging people from using the
>modulo operator to create a range? It could be done by having the RNGs
>return a “RandomValue” type, then defining a mod operator that takes a
>RandomValue and a T (?), and then giving it a deprecation warning +
>fixit. Not sure if that’d be worth the type overhead, but I’m very much in
>favor of encouraging people towards better practices.
>
>- I’m +1 on crashing if we can’t produce a random number.
>
>- What do you think about the philosophical difference of
>Type.random(using:) vs Type.init(randomSource:)?
>
>
> Dave
>
> [0]: https://developer.apple.com/documentation/gameplaykit/gkrandom
> [1]: https://www.youtube.com/watch?v=lg188Ebas9E&feature=youtu.be&t=719
> [2]: https://labs.spotify.com/2014/02/28/how-to-shuffle-songs/
>
>

I think these are some excellent points. Earlier, I think, others also
emphasized this idea of exploring what a really minimal implementation in
the standard library would look like, and I've been thinking about this
overnight.

There is much that is commendable about Alejandro's proposal, but I agree
that there is more than needs to be in the standard library. Here's what I
think the shape of a minimal API would look like, which would
simultaneously enable others to implement their desired functionality as an
end user:

- We need very performant, but otherwise barebones, access to system
randomness so that it can be a building block for everything else. Because
this is so special in that it cannot be seeded or initialized, unlike other
RNGs, we don't need this to be a type, and it doesn't need to conform to a
`RandomNumberGenerator` protocol. It can be as straightforward as one or
both of:

-- A global `func random() -> UInt32`, which is essentially `arc4random` on
macOS/iOS and reads from an appropriate secure source on Linux and other
platforms. One pro of having such a method is that it's a drop-in
replacement for `arc4random()` that's _very_ convenient as a primitive to
build up other random operations; one con is that it encourages modulo
bias, although fortunately mostly only with UInt32.
-- An extension method on `UnsafeMutableRawBufferPointer` named `func
copyRandomBytes()`. This would look a lot like Apple's `SecCopyRandomBytes`
and BSD's `arc4random_buf`.

- Having established the primitive, then we can ask what is the minimum
_useful_ functionality for an end user. I think the answer is a very
judicious subset of the currently proposed functionality:

-- An extension meth

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

2018-01-02 Thread Félix Cloutier via swift-evolution
I'm not sure how much background you have into this thread, but the idea of 
sources and distributions was rejected months ago as almost always too 
cumbersome given that people overwhelmingly want uniform random numbers.

I agree that random() is better as a method. I also think that the default 
Random implementation should be in a class, not a struct. If a generator has 
value semantics, I would expect that two copies would return an identical 
sequence of numbers.

I think that it'll be hard to make a RandomValue that nicely converts to T. 
The best way to discourage modulo is probably to make T.random/T(randomSource:) 
as cumbersome as possible, and Range.random as nice as possible.

> Le 2 janv. 2018 à 11:19, Dave DeLong via swift-evolution 
>  a écrit :
> 
> Just skimmed through the updated proposal and am weighing in with my naïve 
> opinions:
> 
> I’m still highly skeptical of a static “T.random” API. I’ve yet to see a 
> convincing example where it’d be useful to pick a value from the range of all 
> possible values. The only truly useful one I’ve seen is “pick a random bool”, 
> which could easily be done via “[true, false].random()"
> 
> I much prefer the GameplayKit API[0], which breaks the idea of randomness up 
> in to 2 separate concepts:
> A “Source” → Where the random numbers come from
> A “Distribution” → Initialized with a source, it makes sure the produced 
> numbers exhibit a specific distribution over multiple samplings. Ie, a 
> uniform distribution vs a Gaussian distribution, or something like “I want to 
> pick a card from a deck but bias choices towards Spades or Aces”. I’m also 
> reminded of the anecdote of how iTunes had to modify their “playlist shuffle” 
> algorithm to be less random[1], because the true randomness would do weird 
> things that made it seem not random. Spotify had the same problem and 
> solution[2].
> Breaking things up like this would also make it easier to test randomness (by 
> using a replay-able source) but that still follow the parameters of your app 
> (that it has a bell-curve distribution of probabilities, for example)
> 
> I’d still really really really like to see how this could be done as two 
> separate things:
> A minimal implementation in the Standard Library (like, defining the base 
> Source and Distribution protocols, with a single default implementation of 
> each)
> A proposal for a more complete “non-standard library” where the larger array 
> of functionality would be contained. For example, IMO I don’t think the 
> shuffling stuff needs to be in the standard library. This is also where all 
> the cryptographically secure stuff (that your typical app developer does not 
> need) would live.
> 
> The “random” element of a collection/range should be “func random() → 
> Element?”, not “var random: Element?”. Property values shouldn't change 
> between accesses. Ditto the static “Randomizable.random” property.
> 
> What do you think about actively discouraging people from using the modulo 
> operator to create a range? It could be done by having the RNGs return a 
> “RandomValue” type, then defining a mod operator that takes a 
> RandomValue and a T (?), and then giving it a deprecation warning + fixit. 
> Not sure if that’d be worth the type overhead, but I’m very much in favor of 
> encouraging people towards better practices.
> 
> I’m +1 on crashing if we can’t produce a random number. 
> 
> What do you think about the philosophical difference of Type.random(using:) 
> vs Type.init(randomSource:)?
> 
> Dave
> 
> [0]: https://developer.apple.com/documentation/gameplaykit/gkrandom 
> 
> [1]: https://www.youtube.com/watch?v=lg188Ebas9E&feature=youtu.be&t=719 
> 
> [2]: https://labs.spotify.com/2014/02/28/how-to-shuffle-songs/ 
> 
> 
> 
> 
>> On Jan 2, 2018, at 1:35 AM, Alejandro Alonso via swift-evolution 
>> mailto:swift-evolution@swift.org>> wrote:
>> 
>> Hello swift evolution once again, I’ve been hard at work considering every 
>> email and revising the proposal. I’ve made lots of changes and additions to 
>> the proposal to discuss some problems we’ve had (T.random), and walks 
>> through detailed design. You can see the proposal here: 
>> https://github.com/apple/swift-evolution/pull/760 
>>  .
>> 
>> A big issue that lots of people pointed out was `T.random %` and to remove 
>> it completely from the API. To give a gist of why I continue to support 
>> T.random:
>> 
>> 1. Modulo bias misuse is only a problem to types that conform to 
>> `BinaryInteger`. Why remove this functionality if only a portion of the 
>> types have the ability of misuse. `Double.random % 10` is a good example of 
>> where modulo isn’t implemented here as it produces the error, “'%' is 
>> unavailable: Use truncatingRemaind

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

2018-01-02 Thread Dave DeLong via swift-evolution
Just skimmed through the updated proposal and am weighing in with my naïve 
opinions:

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

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

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

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

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

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

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

Dave

[0]: https://developer.apple.com/documentation/gameplaykit/gkrandom 

[1]: https://www.youtube.com/watch?v=lg188Ebas9E&feature=youtu.be&t=719 

[2]: https://labs.spotify.com/2014/02/28/how-to-shuffle-songs/ 




> On Jan 2, 2018, at 1:35 AM, Alejandro Alonso via swift-evolution 
>  wrote:
> 
> Hello swift evolution once again, I’ve been hard at work considering every 
> email and revising the proposal. I’ve made lots of changes and additions to 
> the proposal to discuss some problems we’ve had (T.random), and walks through 
> detailed design. You can see the proposal here: 
> https://github.com/apple/swift-evolution/pull/760 
>  .
> 
> A big issue that lots of people pointed out was `T.random %` and to remove it 
> completely from the API. To give a gist of why I continue to support T.random:
> 
> 1. Modulo bias misuse is only a problem to types that conform to 
> `BinaryInteger`. Why remove this functionality if only a portion of the types 
> have the ability of misuse. `Double.random % 10` is a good example of where 
> modulo isn’t implemented here as it produces the error, “'%' is unavailable: 
> Use truncatingRemainder instead”.
> 
> 2. `Int.random(in: Int.min … Int.max)` doesn’t work. For developers that 
> actually rely on this functionality, the work around that was discussed 
> earlier simply doesn’t work. `Int.min … Int.max`’s count property exceeds 
> that of `Int`’s numerical range. A working work around would be something 
> along the lines of `Int(truncatingIfNeeded: Random.default.next(UInt.self))` 
> which creates a pain point for those developers. As the goal of this proposal 
> to remove pain points regarding random, this change does the opposite.
> 
> I’m interested to hear if anymore discussion around this, or any other issues 
> come up.
> 
> - Alejandro
> 
> On Sep 8, 2017, 11:52 AM -0500, Alejandro Alonso via swift-evolution 
> , 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 
>

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

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

> Hello swift evolution once again, I’ve been hard at work considering every
> email and revising the proposal. I’ve made lots of changes and additions to
> the proposal to discuss some problems we’ve had (T.random), and walks
> through detailed design. You can see the proposal here:
> https://github.com/apple/swift-evolution/pull/760 .
>
> A big issue that lots of people pointed out was `T.random %` and to remove
> it completely from the API. To give a gist of why I continue to support
> T.random:
>
> 1. Modulo bias misuse is only a problem to types that conform to
> `BinaryInteger`. Why remove this functionality if only a portion of the
> types have the ability of misuse. `Double.random % 10` is a good example of
> where modulo isn’t implemented here as it produces the error, “'%' is
> unavailable: Use truncatingRemainder instead”.
>
> 2. `Int.random(in: Int.min … Int.max)` doesn’t work. For developers that
> actually rely on this functionality, the work around that was discussed
> earlier simply doesn’t work. `Int.min … Int.max`’s count property exceeds
> that of `Int`’s numerical range. A working work around would be something
> along the lines of `Int(truncatingIfNeeded: Random.default.next(UInt.self))`
> which creates a pain point for those developers. As the goal of this
> proposal to remove pain points regarding random, this change does the
> opposite.
>
> I’m interested to hear if anymore discussion around this, or any other
> issues come up.
>

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

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


On 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
>
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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 
, 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-12-20 Thread Xiaodi Wu via swift-evolution
On Wed, Dec 20, 2017 at 13:13 Jens Persson  wrote:

> Oh OK, I must have misunderstood this thread:
>
> https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20171204/042034.html
> (
> "The strong opinion of the core team is that such an API should *not* be
> designed with an attempt to service people writing crypto code."
> "It is general goodness if generality for crypto use cases somehow falls
> out of the design.  However, the design for general use shouldn’t suffer
> because of that goal."
> )
>
> I assumed that the Random API would save the user from the trouble of
> making a good choice and implementation (fast and good quality) of a
> "standard" general purpose prng (as well as maybe a cryptographically
> secure one).
>

Providing a cryptographically secure PRNG is necessary but not sufficient
for cryptography. However, many ordinary uses of a general purpose PRNG
will assume that future “random” numbers cannot be guessed by observing a
small number of previous ones. Xoroshiro has its uses, but it would not be
the ideal basis for a general purpose PRNG, especially since we have easy
access to true randomness.

Also, the most commonly recommended ways of converting from eg 64 random
> bits to an int range or a floating point range are unnecessarily bad and
> slow, so I figured the webpage was worth a read, in addition to C++
> stdlib's implementation.
>

I agree it will be critical to ensure that random floating-point values are
truly uniform. All implementors would do well to study the state of the art.


> /Jens
>
>
> On Wed, Dec 20, 2017 at 4:55 PM, Xiaodi Wu  wrote:
>
>> xoroshiro128+ is not a cryptographically secure algorithm and would not
>> be incorporated into the Random API, though it is trivial to implement your
>> own; the proposal outlines sources of randomness that are cryptographically
>> secure.
>>
>>
>>
>> On Wed, Dec 20, 2017 at 09:46 Jens Persson via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>>> I'd like to add a pointer to the information here:
>>> http://xoroshiro.di.unimi.it
>>>
>>> since AFAICS, the xoroshiro128+ generator and the method of "Generating
>>> uniform doubles in the unit interval" should probably be implemented in any
>>> modern general purpose Random API.
>>>
>>> Please correct me if there are more up to date (higher quality and
>>> faster) general purpose generators and ways of converting UInt64 bit
>>> patterns to floating point [0, 1).
>>>
>>> /Jens
>>>
>>>
>>>
>>> On Sun, Dec 3, 2017 at 4:50 AM, Dave Abrahams via swift-evolution <
>>> 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> wrote:


 On Dec 2, 2017, at 6:02 PM, Xiaodi Wu via swift-evolution <
 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 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, lik

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

2017-12-20 Thread Jens Persson via swift-evolution
Oh OK, I must have misunderstood this thread:
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20171204/042034.html
(
"The strong opinion of the core team is that such an API should *not* be
designed with an attempt to service people writing crypto code."
"It is general goodness if generality for crypto use cases somehow falls
out of the design.  However, the design for general use shouldn’t suffer
because of that goal."
)

I assumed that the Random API would save the user from the trouble of
making a good choice and implementation (fast and good quality) of a
"standard" general purpose prng (as well as maybe a cryptographically
secure one).

Also, the most commonly recommended ways of converting from eg 64 random
bits to an int range or a floating point range are unnecessarily bad and
slow, so I figured the webpage was worth a read, in addition to C++
stdlib's implementation.

/Jens


On Wed, Dec 20, 2017 at 4:55 PM, Xiaodi Wu  wrote:

> xoroshiro128+ is not a cryptographically secure algorithm and would not be
> incorporated into the Random API, though it is trivial to implement your
> own; the proposal outlines sources of randomness that are cryptographically
> secure.
>
>
>
> On Wed, Dec 20, 2017 at 09:46 Jens Persson via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>> I'd like to add a pointer to the information here:
>> http://xoroshiro.di.unimi.it
>>
>> since AFAICS, the xoroshiro128+ generator and the method of "Generating
>> uniform doubles in the unit interval" should probably be implemented in any
>> modern general purpose Random API.
>>
>> Please correct me if there are more up to date (higher quality and
>> faster) general purpose generators and ways of converting UInt64 bit
>> patterns to floating point [0, 1).
>>
>> /Jens
>>
>>
>>
>> On Sun, Dec 3, 2017 at 4:50 AM, Dave Abrahams via swift-evolution <
>> 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> wrote:
>>>
>>>
>>> On Dec 2, 2017, at 6:02 PM, Xiaodi Wu via swift-evolution <
>>> 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 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 

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

2017-12-20 Thread Xiaodi Wu via swift-evolution
xoroshiro128+ is not a cryptographically secure algorithm and would not be
incorporated into the Random API, though it is trivial to implement your
own; the proposal outlines sources of randomness that are cryptographically
secure.


On Wed, Dec 20, 2017 at 09:46 Jens Persson via swift-evolution <
swift-evolution@swift.org> wrote:

> I'd like to add a pointer to the information here:
> http://xoroshiro.di.unimi.it
>
> since AFAICS, the xoroshiro128+ generator and the method of "Generating
> uniform doubles in the unit interval" should probably be implemented in any
> modern general purpose Random API.
>
> Please correct me if there are more up to date (higher quality and faster)
> general purpose generators and ways of converting UInt64 bit patterns to
> floating point [0, 1).
>
> /Jens
>
>
>
> On Sun, Dec 3, 2017 at 4:50 AM, Dave Abrahams via swift-evolution <
> 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> wrote:
>>
>>
>> On Dec 2, 2017, at 6:02 PM, Xiaodi Wu via swift-evolution <
>> 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 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
>> 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
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2017-12-20 Thread Jens Persson via swift-evolution
I'd like to add a pointer to the information here:
http://xoroshiro.di.unimi.it

since AFAICS, the xoroshiro128+ generator and the method of "Generating
uniform doubles in the unit interval" should probably be implemented in any
modern general purpose Random API.

Please correct me if there are more up to date (higher quality and faster)
general purpose generators and ways of converting UInt64 bit patterns to
floating point [0, 1).

/Jens



On Sun, Dec 3, 2017 at 4:50 AM, Dave Abrahams via swift-evolution <
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> wrote:
>
>
> On Dec 2, 2017, at 6:02 PM, Xiaodi Wu via swift-evolution <
> 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 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
> 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-12-02 Thread Dave Abrahams via swift-evolution
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
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2017-12-02 Thread Kyle Murray via swift-evolution

> 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


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

2017-12-02 Thread Chris Lattner via swift-evolution

> On Dec 2, 2017, at 6:02 PM, Xiaodi Wu via swift-evolution 
>  wrote:
> 
> My point is that our entire design process has been geared towards a 
> reasonable, best-effort general-use API: It is being designed by community 
> members who are not specialized in this particular subfield. It is explicitly 
> being design for common, general use cases in mind. And the implementation 
> will come with no guarantee as to suitability for crypto, nor should it have 
> to.

+1.  

Even if we tried to make an RNG for crypto use it would not be widely used for 
crypto because it would not be good enough for someone who really really cares. 
 At the same time, general users would suffer due to the design decisions 
aligned at making it suitable for crypto.

In the end, it would not serve either audience well.  It is better to 
acknowledge up front that the goal of the stdlib is “general use” and optimize 
to ensure that use case is well served.

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


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

2017-12-02 Thread Xiaodi Wu via swift-evolution
On Sat, Dec 2, 2017 at 19:02 Greg Parker  wrote:

>
> On Dec 2, 2017, at 1:09 PM, Xiaodi Wu via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> On Sat, Dec 2, 2017 at 6:00 AM, Brent Royal-Gordon  > wrote:
>
>> On Dec 1, 2017, at 10:37 PM, Xiaodi Wu via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>> That said, I am not sure that this proposal should give any pretense of
>> being suitable for cryptographic use. On implementation, the code will not
>> have been audited for that purpose, although the author very rightly
>> attempts to use the "best" possible sources of entropy available for each
>> platform. Perhaps explicitly _not_ supporting cryptographic operations is
>> the more Swifty way to go (in the sense that, where possible, Swift API
>> design aims to help users avoid footguns).
>>
>>
>> People will use it for crypto whether we want them to or not.
>>
>
> People are going to do all sorts of unanticipated things, sure. But this
> doesn't mean that we shouldn't consider how we may best encourage users to
> avoid _unintentional_ common pitfalls.
>
> There are options to explore here. Consider, for example--and I'm not
> suggesting that we be this verbose, but it is illustrative of the
> trade-offs which are possible to keep in mind--if certain methods were very
> clear that the result is *pseudorandom* and potentially *insecure*:
> `(0..<9).insecurePseudorandomElement`. Clearly, fewer people would use this
> method for crypto.
>
>
> But what *should* they use instead of our API? The OS-provided CSPRNG is
> almost certainly going to be the most secure thing available in the absence
> of specialized hardware. We should not deliberately scare users away from
> our API if there is nothing better on offer.
>

>
It’s not about OS-provided CSPRNG. It’s about the design and implementation
of _this proposal_ on top of the CSPRNG.

Earlier, we discussed how this API should minimize the number of optional
return values to improve user ergonomics. Instead, the returned value
should be a reasonable best-effort at randomness. This is sensible for a
general-use API, but it is unsuitable for a crypto-oriented API.

David Waite criticizes GameplayKit as lacking in crypto-oriented
functions—the implication being that we ought to provide them here. I
disagree. My point is that our entire design process has been geared
towards a reasonable, best-effort general-use API: It is being designed by
community members who are not specialized in this particular subfield. It
is explicitly being design for common, general use cases in mind. And the
implementation will come with no guarantee as to suitability for crypto,
nor should it have to.

Therefore, I reason, we ought not to extend the design with functions that
are explicitly geared towards crypto using primitive operations that we
haven’t audited for such suitability. 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.
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2017-12-02 Thread Greg Parker via swift-evolution

> On Dec 2, 2017, at 1:09 PM, Xiaodi Wu via swift-evolution 
>  wrote:
> 
> On Sat, Dec 2, 2017 at 6:00 AM, Brent Royal-Gordon  > wrote:
>> On Dec 1, 2017, at 10:37 PM, Xiaodi Wu via swift-evolution 
>> mailto:swift-evolution@swift.org>> wrote:
>> 
>> That said, I am not sure that this proposal should give any pretense of 
>> being suitable for cryptographic use. On implementation, the code will not 
>> have been audited for that purpose, although the author very rightly 
>> attempts to use the "best" possible sources of entropy available for each 
>> platform. Perhaps explicitly _not_ supporting cryptographic operations is 
>> the more Swifty way to go (in the sense that, where possible, Swift API 
>> design aims to help users avoid footguns).
> 
> People will use it for crypto whether we want them to or not.
> 
> People are going to do all sorts of unanticipated things, sure. But this 
> doesn't mean that we shouldn't consider how we may best encourage users to 
> avoid _unintentional_ common pitfalls.
> 
> There are options to explore here. Consider, for example--and I'm not 
> suggesting that we be this verbose, but it is illustrative of the trade-offs 
> which are possible to keep in mind--if certain methods were very clear that 
> the result is *pseudorandom* and potentially *insecure*: 
> `(0..<9).insecurePseudorandomElement`. Clearly, fewer people would use this 
> method for crypto.

But what *should* they use instead of our API? The OS-provided CSPRNG is almost 
certainly going to be the most secure thing available in the absence of 
specialized hardware. We should not deliberately scare users away from our API 
if there is nothing better on offer.


-- 
Greg Parker gpar...@apple.com Runtime Wrangler


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


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

2017-12-02 Thread Xiaodi Wu via swift-evolution
On Sat, Dec 2, 2017 at 6:00 AM, Brent Royal-Gordon 
wrote:

> On Dec 1, 2017, at 10:37 PM, Xiaodi Wu via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> That said, I am not sure that this proposal should give any pretense of
> being suitable for cryptographic use. On implementation, the code will not
> have been audited for that purpose, although the author very rightly
> attempts to use the "best" possible sources of entropy available for each
> platform. Perhaps explicitly _not_ supporting cryptographic operations is
> the more Swifty way to go (in the sense that, where possible, Swift API
> design aims to help users avoid footguns).
>
>
> People will use it for crypto whether we want them to or not.
>

People are going to do all sorts of unanticipated things, sure. But this
doesn't mean that we shouldn't consider how we may best encourage users to
avoid _unintentional_ common pitfalls.

There are options to explore here. Consider, for example--and I'm not
suggesting that we be this verbose, but it is illustrative of the
trade-offs which are possible to keep in mind--if certain methods were very
clear that the result is *pseudorandom* and potentially *insecure*:
`(0..<9).insecurePseudorandomElement`. Clearly, fewer people would use this
method for crypto.

None of the proposals involve actually writing cryptographic primitives,
> just calling out to well-known functions like `arc4random()` or reading
> from special devices like `/dev/urandom`. I would hope that Apple's
> security team can spare the time to review the security-critical parts and
> sign off on them, and I'd be perfectly happy to see this proposal be
> approved but the final merge into the language be deferred until they've
> taken a look at it.
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2017-12-02 Thread Erica Sadun via swift-evolution
On Dec 1, 2017, at 11:23 PM, David Waite  wrote:
> 
> 
> 
>> On Dec 1, 2017, at 11:05 AM, Erica Sadun via swift-evolution 
>> mailto:swift-evolution@swift.org>> wrote:
>> 
>> I'd like to put forth that Gameplay Kit offers a perfectly cromulent model 
>> of random number generation and API. Why not take that as a starting point, 
>> Swiftify it so it becomes a cross platform solution, and then apply the 
>> specific questions of sequences, collections, and indices as a second step?  
>> 
>> I don't support intermingling random functionality with existing core types.
>> 
> 
> GameplayKit randomization has a number of API deficiencies that we can’t 
> easily/efficiently solve by wrapping it in Swift.
> 
> Most significantly, it is not designed to support any cryptographic 
> operations (which I believe is why they never added a nextBytes() or 
> equivalent method).
> 
> For GameplayKit this is fine - the design focuses on being able to get the 
> distribution appropriate for your game, and being able to have identical 
> pseudorandom number sequences for each device in a multiplayer scenario. They 
> went as far as to require all random sources to support NSSecureCoding so 
> that they may be persisted and/or serialized over the wire, which precludes a 
> GKRandomSource from being based on the system random sources.
> 
> -DW

I wasn't suggesting wrapping as that would not provide a cross platform 
solution. Instead of re-inventing the wheel, we may profit from the approaches 
already explored and real-world tested in prior art and existing standards.

-- E

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


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

2017-12-02 Thread Brent Royal-Gordon via swift-evolution
> On Dec 1, 2017, at 10:37 PM, Xiaodi Wu via swift-evolution 
>  wrote:
> 
> That said, I am not sure that this proposal should give any pretense of being 
> suitable for cryptographic use. On implementation, the code will not have 
> been audited for that purpose, although the author very rightly attempts to 
> use the "best" possible sources of entropy available for each platform. 
> Perhaps explicitly _not_ supporting cryptographic operations is the more 
> Swifty way to go (in the sense that, where possible, Swift API design aims to 
> help users avoid footguns).

People will use it for crypto whether we want them to or not.

None of the proposals involve actually writing cryptographic primitives, just 
calling out to well-known functions like `arc4random()` or reading from special 
devices like `/dev/urandom`. I would hope that Apple's security team can spare 
the time to review the security-critical parts and sign off on them, and I'd be 
perfectly happy to see this proposal be approved but the final merge into the 
language be deferred until they've taken a look at it.

-- 
Brent Royal-Gordon
Architechies

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


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

2017-12-01 Thread Xiaodi Wu via swift-evolution
s: 0.6)
>>>
>>>
>>> This means that our default RandomSource needs to be publicly available,
>>> so that the custom functions can use it as the default…
>>>
>>>
>> It does not. Having actually implemented some version of these APIs, it's
>> readily apparent now to me that all custom types can simply call
>> Int.random(in:) (or UnsafeRawBufferPointer.random(byteCount:), or
>> whatever else we want to have in the standard library) to get random values
>> from the default RNG for any built-in type and size. The actual default
>> random need never be exposed publicly, and since its functions are strictly
>> redundant to these other APIs (which, of course, are the "currency" APIs
>> that our purpose here is to design and make public), the default random is
>> required only for internal implementation of the "currency" APIs and (a) is
>> better off *not* exposed; (b) doesn't need to be of the same type as other
>> RNGs, conform to the same protocols, or for that matter, does not even need
>> to be a type or be written in Swift.
>>
>>
>> Assuming we have two versions of whatever new random operations we add,
>> where one takes an RNG as a parameter and the other uses the default, how
>> would I add functionality that matches this pattern in my own code? The
>> standard library would look have code like this:
>>
>> extension MutableCollection {
>> func shuffle(using rng: RNG) {
>> // shuffle the elements
>> }
>>
>> func shuffle() {
>> shuffle(using: _privateDefaultRNG)
>> }
>> }
>>
>> Let’s say I’m writing something for my own app or library, and want to
>> add two related methods with the same pattern:
>>
>> extension Collection {
>> func randomRange(length: Int, using rng: RNG) -> [SubSequence] {
>> // select a starting point in 0..> // verify that florps are still sideways
>> // etc
>> }
>>
>> func randomRange(length: Int) {
>> return randomRange(length: Int, using: ?)
>> }
>> }
>>
>> What do I put in the second method so I don’t have to implement this
>> twice?
>>
>
> If this is to be used, as others say, to permit obtaining a random value
> of a certain distribution passed in as the parameter `using`, then to
> implement it correctly you *must* implement it twice. Actually, you may
> have to implement it not just twice but differently for each distribution,
> so I'm not sure that it's a viable design for the stated use case.
>
>
> I don't think I've seen anyone propose that you would haven't different
> distributions by passing different RNGs.
>

I do believe that Dave DeLong did say something along those lines earlier
in the thread. The design of the C++ standard library
RandomNumberDistribution function objects does have some echoes here,
although the actual design is somewhat different.

Is there any way any of this works for an RNG that isn't providing uniform
> random bits? I don't understand how any of these primitive methods would
> work with an RNG that was doing something different, regardless of how the
> methods are spelled.
>

It may well not; that said, nothing in the proposal's RNG protocol
specifies a semantic requirement regarding the distribution of the random
bits produced, and it is not out of the question that someone may attempt
to design a suite of RNGs that provide varying distributions.

The purpose of the (using:) versions is to allow for RNGs that meet
> different requirements from the default: seedable/repeatable, faster, more
> secure, etc.
>

Yes, I understand. Even then: is a struct that has two stored properties
more secure when it is initialized with two more secure values? That may
depend on what the struct does with those values, no?


> -Nate
>>
>>
>> 👍
>>>
>>>
>>> Thanks,
>>> Jon
>>>
>>>
>>> On Nov 27, 2017, at 10:14 AM, TellowKrinkle via swift-evolution <
>>> swift-evolution@swift.org> wrote:
>>>
>>> You say that all the `.random`s have different semantics, but to me (at
>>> least), they are all very similar.  All the methods can be summarized as
>>> selecting a single random element from a collection
>>> `[0, 2, 3].random` selects a single element from the given collection
>>> `Int.random(in: 0…8)` selects a single element from the given range
>>> `Int.random` has no range, but selects a single element from 

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

2017-12-01 Thread Xiaodi Wu via swift-evolution
On Sat, Dec 2, 2017 at 12:23 AM, David Waite 
wrote:

>
>
> On Dec 1, 2017, at 11:05 AM, Erica Sadun via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> I'd like to put forth that Gameplay Kit offers a perfectly cromulent model
> of random number generation and API. Why not take that as a starting point,
> Swiftify it so it becomes a cross platform solution, and then apply the
> specific questions of sequences, collections, and indices as a second step?
>
>
> I don't support intermingling random functionality with existing core
> types.
>
>
> GameplayKit randomization has a number of API deficiencies that we can’t
> easily/efficiently solve by wrapping it in Swift.
>
> Most significantly, it is not designed to support any cryptographic
> operations (which I believe is why they never added a nextBytes() or
> equivalent method).
>
> For GameplayKit this is fine - the design focuses on being able to get the
> distribution appropriate for your game, and being able to have identical
> pseudorandom number sequences for each device in a multiplayer scenario.
> They went as far as to require all random sources to support NSSecureCoding
> so that they may be persisted and/or serialized over the wire, which
> precludes a GKRandomSource from being based on the system random sources.
>

That said, I am not sure that this proposal should give any pretense of
being suitable for cryptographic use. On implementation, the code will not
have been audited for that purpose, although the author very rightly
attempts to use the "best" possible sources of entropy available for each
platform. Perhaps explicitly _not_ supporting cryptographic operations is
the more Swifty way to go (in the sense that, where possible, Swift API
design aims to help users avoid footguns).
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2017-12-01 Thread David Waite via swift-evolution


> On Dec 1, 2017, at 11:05 AM, Erica Sadun via swift-evolution 
>  wrote:
> 
> I'd like to put forth that Gameplay Kit offers a perfectly cromulent model of 
> random number generation and API. Why not take that as a starting point, 
> Swiftify it so it becomes a cross platform solution, and then apply the 
> specific questions of sequences, collections, and indices as a second step?  
> 
> I don't support intermingling random functionality with existing core types.
> 

GameplayKit randomization has a number of API deficiencies that we can’t 
easily/efficiently solve by wrapping it in Swift.

Most significantly, it is not designed to support any cryptographic operations 
(which I believe is why they never added a nextBytes() or equivalent method).

For GameplayKit this is fine - the design focuses on being able to get the 
distribution appropriate for your game, and being able to have identical 
pseudorandom number sequences for each device in a multiplayer scenario. They 
went as far as to require all random sources to support NSSecureCoding so that 
they may be persisted and/or serialized over the wire, which precludes a 
GKRandomSource from being based on the system random sources.

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


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

2017-12-01 Thread Jonathan Hull via swift-evolution

> On Dec 1, 2017, at 9:39 AM, Martin Waitz  wrote:
> 
> Hi,
> 
>> With a protocol defining random() and random(in:), you could write generic 
>> algorithms on things which know how to create themselves from a RNG.  With 
>> your approach the RNG has to provide a way to get a random value for each 
>> type you want to support.
> 
> This is right, if we want a generic prototype for construction of random 
> objects, well then we need such a protocol and a new method or initializer.
> However, I‘m not yet convinced that such a protocol is necessary.
> Most objects will be constructed using randomized values, according to the 
> use case at hand. A generic randomizable protocol would not help here.

I’m not sure how you intend to get a random value from a Range without 
something like this. 

But even ignoring that for the moment, I have a version of this in my own code 
and find it quite useful.  What I do is setup a series of constraints on the 
values I want (e.g. the range I want them in) and then I generically generate a 
lazy collection of random values of that type.  Thus, I can ask for colors with 
certain properties, and then I receive a collection of random colors with those 
properties which I use to create patterns and graphic effects.


>> For example, without random(in:) or random(), how would you get a CGFloat 
>> between 0 and 1?  Ranges are only collections if they are countable…
> 
> I was assuming that there would be a random.draw(from:) for ranges.

Sure, but Ranges of what?  Ranges of CGFloats are very different than Ranges of 
Ints, you need some cooperation from the type itself. This is my main point.


>>> extension RandomFoo {
>>>  func draw(from urn: T) -> T.Element? {
>>>  guard !urn.isEmpty else { return nil }
>>>  let idx = draw(from: urn.indices)
>>>  return urn[idx]
>>>  }
>>> }
>>> 
>> This will call itself repeatedly and hang...
> 
> You are right, Collection.indices is also a Collection. We have to explicitly 
> use the range here.
> 
>>> We just have to define one base protocol for such extensions. Every random 
>>> number generator then automatically knows how to draw elements from ranges 
>>> and collections.
>> 
>> It isn’t automatic, thought.  How would I get a random color?
> 
> This has already been discussed: you either want some random color from a 
> fixed set, or you want to produce a new color using some random values. A 
> completely random color it totally useless.

I wouldn’t say completely useless.  In the example above, I usually constrain 
my random colors to have a specific effect, but completely random has its own 
look (which I mainly use for debugging purposes).  As I mentioned earlier in 
the thread, the protocol can be augmented by UIColor to provide a way to only 
get random values with certain characteristics.

Yes, colors can be built from smaller primitives, but it is nice to have the 
type do that itself so you can continue to build on it generically.

In the examples you have given, everything has to be special cased (even 
getting a random Bool requires me to list out the options [true, false]). That 
isn’t useful for building large scale structures generically.

I am not arguing that we shouldn’t be able to get a random element from a 
collection or range… just that we should build this in a way which is easy to 
build on and modify.



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


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

2017-12-01 Thread Erica Sadun via swift-evolution


> On Nov 30, 2017, at 5:21 PM, Xiaodi Wu via swift-evolution 
>  wrote:
> 
> On Thu, Nov 30, 2017 at 5:24 PM, Nate Cook  > wrote:
>> On Nov 30, 2017, at 4:30 PM, Xiaodi Wu via swift-evolution 
>> mailto:swift-evolution@swift.org>> wrote:
>> 
>> On Thu, Nov 30, 2017 at 3:58 PM, Dave DeLong via swift-evolution 
>> mailto:swift-evolution@swift.org>> wrote:
>> 
>> 
>>> On Nov 30, 2017, at 2:48 PM, Jonathan Hull via swift-evolution 
>>> mailto:swift-evolution@swift.org>> wrote:
>>> 
>>> I would personally go with:
>>> 
>>> Int.random //Returns a random Int
>> 
>> “Type.random” is so rarely used as to not be worth the addition, IMO. If you 
>> really need a random element from the *entire* domain, then I think you 
>> should have to manually create the ClosedRange yourself.
>> 
>>> Int.random(in: ClosedRange) //Works for Comparable types. Gives a 
>>> result from the closed range. Closed Range is never empty.
>> 
>> This is redundant. In order to pick a random element, you’re saying I should 
>> have to do “Int.random(0 ..< 10)”? The redundancy here is that I have to 
>> specify Int twice: once for the “.random” call, and again for the type of 
>> the range. We can do better than that.
> 
> I don’t see how this is redundant—do you mean that you’d need to write out 
> the type name instead of writing `(0..<10).random()!`? I continue to be of 
> the opinion that picking a random integer/floating-point value/Boolean and 
> picking a random element from a collection are two different operations. Yes, 
> there’s overlap between the two, but they’re different enough that having two 
> ways to choose an integer between 0 and 10 would be fine.
> 
> As I wrote elsewhere, if they're sufficiently different enough, then they 
> ought to have distinct names. If they are not, then there ought to be only 
> one of them. I'm no longer sure myself of which one I'd prefer, but in no 
> case should there be two things named "random."
> 
> If the proposal to make `IndexDistance == Int` is accepted, then ranges 
> cannot conform to Collection and we encounter some interesting difficulties 
> attempting to index into such a collection to pick a random value.

I'd like to put forth that Gameplay Kit offers a perfectly cromulent model of 
random number generation and API. Why not take that as a starting point, 
Swiftify it so it becomes a cross platform solution, and then apply the 
specific questions of sequences, collections, and indices as a second step?  

I don't support intermingling random functionality with existing core types.

-- E


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


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

2017-12-01 Thread Martin Waitz via swift-evolution
Hi,

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

This is right, if we want a generic prototype for construction of random 
objects, well then we need such a protocol and a new method or initializer.
However, I‘m not yet convinced that such a protocol is necessary.
Most objects will be constructed using randomized values, according to the use 
case at hand. A generic randomizable protocol would not help here.

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

I was assuming that there would be a random.draw(from:) for ranges.

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

You are right, Collection.indices is also a Collection. We have to explicitly 
use the range here.

>> We just have to define one base protocol for such extensions. Every random 
>> number generator then automatically knows how to draw elements from ranges 
>> and collections.
> 
> It isn’t automatic, thought.  How would I get a random color?

This has already been discussed: you either want some random color from a fixed 
set, or you want to produce a new color using some random values. A completely 
random color it totally useless.

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


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

2017-12-01 Thread Mike Kluev via swift-evolution
on Thu, 30 Nov 2017 15:08:55 -0800 Jonathan Hull  wrote:

>
> I think it is important to have Type.random as the base because there are
> many types which would conform (not just Int & Double).



what would Double.random return though? a "uniformly distributed value" in
the range minus DBL_MAX ...  plus DBL_MAX ?

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


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

2017-12-01 Thread Jonathan Hull via swift-evolution

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

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

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

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


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


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

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



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


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

2017-11-30 Thread Martin Waitz via swift-evolution
Hello,

> The collection is a subject which has elements, and we are asking for one of 
> them at random.

it has elements, sure.
And because of its structure, it has a first and a last element and whatever.
But that random element is not an inherent property of the collection.

I find it much more natural to use the random number generator to draw random 
elements from collections than the other way round.
That approach also completely side-steps the problem with having to define 
default arguments. The user can just use any random number generator she has. 
Obviously, it makes sense to provide a default one named `random` to make it 
easily accessible.

>>> var list = [1,2,3,4]
>>> let a:Int? = list.randomElement //List is still [1,2,3,4] and ‘a’ contains 
>>> one of the elements
>> 
>> Instead I would prefer to have something like:
>> 
>> let a = random.draw(from: list)
> 
> But now the RNG has to understand the concept of collections. I would argue 
> it is much cleaner to write an extension on Collection.
> 
> func randomElement(using source: RandomSource = .default) -> Element? {
>   guard !isEmpty else {return nil}
>   let idx = Int.random(in: 0…(count - 1), using: source)
>   return self[idx]
> }

But then the Collection has to understand the concept of random numbers. ;-)
Well both approaches are equally clean from this point of view:

extension RandomFoo {
func draw(from urn: T) -> T.Element? {
guard !urn.isEmpty else { return nil }
let idx = draw(from: urn.indices)
return urn[idx]
}
}

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

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


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

2017-11-30 Thread Nate Cook via swift-evolution
random(saturation: 0.2…0.2, brightness: 0.6…0.6) 
>>>>> 
>>>>> There would probably also be a convenience version taking CGFloats and 
>>>>> passing them to the real function as ranges:
>>>>> 
>>>>>   let myColor = UIColor.random(saturation: 0.2, brightness: 0.6)
>>>>> 
>>>>> 
>>>>> This means that our default RandomSource needs to be publicly available, 
>>>>> so that the custom functions can use it as the default…
>>> 
>>> It does not. Having actually implemented some version of these APIs, it's 
>>> readily apparent now to me that all custom types can simply call 
>>> Int.random(in:) (or UnsafeRawBufferPointer.random(byteCount:), or 
>>> whatever else we want to have in the standard library) to get random values 
>>> from the default RNG for any built-in type and size. The actual default 
>>> random need never be exposed publicly, and since its functions are strictly 
>>> redundant to these other APIs (which, of course, are the "currency" APIs 
>>> that our purpose here is to design and make public), the default random is 
>>> required only for internal implementation of the "currency" APIs and (a) is 
>>> better off *not* exposed; (b) doesn't need to be of the same type as other 
>>> RNGs, conform to the same protocols, or for that matter, does not even need 
>>> to be a type or be written in Swift.
>> 
>> Assuming we have two versions of whatever new random operations we add, 
>> where one takes an RNG as a parameter and the other uses the default, how 
>> would I add functionality that matches this pattern in my own code? The 
>> standard library would look have code like this:
>> 
>> extension MutableCollection {
>> func shuffle(using rng: RNG) {
>> // shuffle the elements
>> }
>> 
>> func shuffle() {
>> shuffle(using: _privateDefaultRNG)
>> }
>> }
>> 
>> Let’s say I’m writing something for my own app or library, and want to add 
>> two related methods with the same pattern:
>> 
>> extension Collection {
>> func randomRange(length: Int, using rng: RNG) -> [SubSequence] {
>> // select a starting point in 0..> // verify that florps are still sideways
>> // etc
>> }
>> 
>> func randomRange(length: Int) {
>> return randomRange(length: Int, using: ?)
>> }
>> }
>> 
>> What do I put in the second method so I don’t have to implement this twice?
> 
> If this is to be used, as others say, to permit obtaining a random value of a 
> certain distribution passed in as the parameter `using`, then to implement it 
> correctly you *must* implement it twice. Actually, you may have to implement 
> it not just twice but differently for each distribution, so I'm not sure that 
> it's a viable design for the stated use case.

I don't think I've seen anyone propose that you would haven't different 
distributions by passing different RNGs. Is there any way any of this works for 
an RNG that isn't providing uniform random bits? I don't understand how any of 
these primitive methods would work with an RNG that was doing something 
different, regardless of how the methods are spelled. The purpose of the 
(using:) versions is to allow for RNGs that meet different requirements from 
the default: seedable/repeatable, faster, more secure, etc.

> 
>> -Nate
>> 
>> 
>>>> 👍 
>>>> 
>>>>> 
>>>>> Thanks,
>>>>> Jon
>>>>> 
>>>>> 
>>>>>> On Nov 27, 2017, at 10:14 AM, TellowKrinkle via swift-evolution 
>>>>>>  wrote:
>>>>>> 
>>>>>> You say that all the `.random`s have different semantics, but to me (at 
>>>>>> least), they are all very similar.  All the methods can be summarized as 
>>>>>> selecting a single random element from a collection
>>>>>> `[0, 2, 3].random` selects a single element from the given collection
>>>>>> `Int.random(in: 0…8)` selects a single element from the given range
>>>>>> `Int.random` has no range, but selects a single element from the 
>>>>>> collection of all ints (equivalent to if the above method had a default 
>>>>>> value for its range)
>>>>>> So to me these are all doing the same operation, just with different

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

2017-11-30 Thread Jonathan Hull via swift-evolution

> On Nov 30, 2017, at 4:11 PM, Xiaodi Wu  wrote:
> 
> On Thu, Nov 30, 2017 at 5:29 PM, Jonathan Hull  > wrote:
> 
>> On Nov 30, 2017, at 2:30 PM, Xiaodi Wu > > wrote:
>> 
>> On Thu, Nov 30, 2017 at 3:58 PM, Dave DeLong via swift-evolution 
>> mailto:swift-evolution@swift.org>> wrote:
>> 
>> 
>>> On Nov 30, 2017, at 2:48 PM, Jonathan Hull via swift-evolution 
>>> mailto:swift-evolution@swift.org>> wrote:
>>> 
>>> I would personally go with:
>>> 
>>> Int.random //Returns a random Int
>> 
>> “Type.random” is so rarely used as to not be worth the addition, IMO. If you 
>> really need a random element from the *entire* domain, then I think you 
>> should have to manually create the ClosedRange yourself.
>> 
>>> Int.random(in: ClosedRange) //Works for Comparable types. Gives a 
>>> result from the closed range. Closed Range is never empty.
>> 
>> This is redundant. In order to pick a random element, you’re saying I should 
>> have to do “Int.random(0 ..< 10)”? The redundancy here is that I have to 
>> specify Int twice: once for the “.random” call, and again for the type of 
>> the range. We can do better than that.
>> 
>>> [0,2,3].randomElement //Returns a random element from the collection
>> 
>> I strongly believe this should be a method, not a property. Properties, like 
>> .first and .last, are expected to return the same value each time you access 
>> them. “.random” inherently breaks that.
>>  
>> FWIW--and this isn't a vote, I know--I largely agree with Dave DeLong's 
>> conclusions above, and for substantially the same reasons.
>>> 
>>> Then a version of each with a ‘using:’ parameter which takes a 
>>> generator/source:
>>> 
>>> Int.random(using: RandomSource) //Returns a random Int using the given 
>>> source of randomness
>>> Int.random(in: ClosedRange, using: RandomSource)
>>> [0,2,3].randomElement(using: RandomSource)
>>> 
>>> In my own RandomSource & RandomSourceCreatable protocols, I frequently use 
>>> random colors and sizes as well.  The issue there is that you really want a 
>>> closed range for each dimension. I wish Swift had a better notion of 
>>> dimensionality baked into the language. 
>>> 
>>> What I ended up doing was having a “constraints” parameter which took an 
>>> array of constraints which corresponded to various dimensions.  It works 
>>> for me, but it might be a bit complex for something in the standard library.
>>> 
>>> Honestly, given the current capabilities of Swift what this really calls 
>>> for is custom initializers/functions for dimensional types:
>>> 
>>> UIColor.random //This comes from the protocol
>>> UIColor.random(hue: ClosedRange = 0…1, saturation: 
>>> ClosedRange = 0…1, brightness: ClosedRange = 0…1, alpha: 
>>> ClosedRange = 1…1)
>>> //…and of course the same as above, but with ‘using:'
>>> 
>>> Then you can easily get random colors which look like they belong together:
>>> 
>>> let myColor = UIColor.random(saturation: 0.2…0.2, brightness: 0.6…0.6) 
>>> 
>>> There would probably also be a convenience version taking CGFloats and 
>>> passing them to the real function as ranges:
>>> 
>>> let myColor = UIColor.random(saturation: 0.2, brightness: 0.6)
>>> 
>>> 
>>> This means that our default RandomSource needs to be publicly available, so 
>>> that the custom functions can use it as the default…
>> 
>> 
>> It does not. Having actually implemented some version of these APIs, it's 
>> readily apparent now to me that all custom types can simply call 
>> Int.random(in:) (or UnsafeRawBufferPointer.random(byteCount:), or 
>> whatever else we want to have in the standard library) to get random values 
>> from the default RNG for any built-in type and size. The actual default 
>> random need never be exposed publicly, and since its functions are strictly 
>> redundant to these other APIs (which, of course, are the "currency" APIs 
>> that our purpose here is to design and make public), the default random is 
>> required only for internal implementation of the "currency" APIs and (a) is 
>> better off *not* exposed; (b) doesn't need to be of the same type as other 
>> RNGs, conform to the same protocols, or for that matter, does not even need 
>> to be a type or be written in Swift.
> 
> I have also implemented some version of these APIs, both for Random and 
> RepeatablyRandom sources.
> 
> I get what you are saying about just being able to use the constructs from 
> Int, etc…, but we still need a public default.  Let me give a concrete 
> example of CGSize.  Yes, we want to just use CGFloat’s random, but if we 
> don’t have a publicly available way to call the default then we have to 
> implement the same algorithm twice, which is problematic. (Code written in 
> Mail)
> 
> static func random(width widthRange: ClosedRange, height 
> heightRange: ClosedRange, using source: RandomSource = .default) -> 
> CGSize {
>   let w = CGFloat.random(in: widthRange, using: sour

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

2017-11-30 Thread Xiaodi Wu via swift-evolution
efault RNG for any built-in type and size. The actual default
> random need never be exposed publicly, and since its functions are strictly
> redundant to these other APIs (which, of course, are the "currency" APIs
> that our purpose here is to design and make public), the default random is
> required only for internal implementation of the "currency" APIs and (a) is
> better off *not* exposed; (b) doesn't need to be of the same type as other
> RNGs, conform to the same protocols, or for that matter, does not even need
> to be a type or be written in Swift.
>
>
> Assuming we have two versions of whatever new random operations we add,
> where one takes an RNG as a parameter and the other uses the default, how
> would I add functionality that matches this pattern in my own code? The
> standard library would look have code like this:
>
> extension MutableCollection {
> func shuffle(using rng: RNG) {
> // shuffle the elements
> }
>
> func shuffle() {
> shuffle(using: _privateDefaultRNG)
> }
> }
>
> Let’s say I’m writing something for my own app or library, and want to add
> two related methods with the same pattern:
>
> extension Collection {
> func randomRange(length: Int, using rng: RNG) -> [SubSequence] {
> // select a starting point in 0.. // verify that florps are still sideways
> // etc
> }
>
> func randomRange(length: Int) {
> return randomRange(length: Int, using: ?)
> }
> }
>
> What do I put in the second method so I don’t have to implement this twice?
>

If this is to be used, as others say, to permit obtaining a random value of
a certain distribution passed in as the parameter `using`, then to
implement it correctly you *must* implement it twice. Actually, you may
have to implement it not just twice but differently for each distribution,
so I'm not sure that it's a viable design for the stated use case.

-Nate
>
>
> 👍
>>
>>
>> Thanks,
>> Jon
>>
>>
>> On Nov 27, 2017, at 10:14 AM, TellowKrinkle via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>> You say that all the `.random`s have different semantics, but to me (at
>> least), they are all very similar.  All the methods can be summarized as
>> selecting a single random element from a collection
>> `[0, 2, 3].random` selects a single element from the given collection
>> `Int.random(in: 0…8)` selects a single element from the given range
>> `Int.random` has no range, but selects a single element from the
>> collection of all ints (equivalent to if the above method had a default
>> value for its range)
>> So to me these are all doing the same operation, just with different
>> types of inputs
>>
>> 2017/11/24 20:07、Alejandro Alonso のメール:
>>
>>
>> - Alejandro
>>
>> -- Forwarded message --
>> *From:* Xiaodi Wu 
>> *Date:* Nov 24, 2017, 3:05 PM -0600
>> *To:* Alejandro Alonso 
>> *Cc:* Brent Royal-Gordon , Steve Canon via
>> swift-evolution 
>> *Subject:* Re: [swift-evolution] [Proposal] Random Unification
>>
>> On Fri, Nov 24, 2017 at 2:55 PM, Alejandro Alonso > > wrote:
>>
>>> 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 must disagree quite strongly here. The various facilities you name
>> "random" have different semantics, and differences in semantics should be
>> reflected in differences in names. It doesn't matter that some people don't
>> find it confusing; it is objectively the case that you have named multiple
>> distinct facilities with the same name, which leads to confusion. I, for
>> one, get confused, and you can see on this list that people are using
>> arguments about one property named "random" to discuss another property
>> named "random". This is quite an intolerable situation.
>>
>> 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. Th

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

2017-11-30 Thread Jonathan Hull via swift-evolution
> On Nov 30, 2017, at 3:46 PM, Martin Waitz  wrote:
> 
> Hello Jonathan,
> 
>> For collections, I think we should call returning a random element 
>> -randomElement, and choosing a random element without replacement 
>> -popRandomElement
> 
> I disagree because I don’t think that the random data is a property of the 
> collection.
> The collection is not the subject which has random elements, it’s more the 
> object which is used when drawing an element.

The collection is a subject which has elements, and we are asking for one of 
them at random.


>> var list = [1,2,3,4]
>> let a:Int? = list.randomElement //List is still [1,2,3,4] and ‘a’ contains 
>> one of the elements
> 
> Instead I would prefer to have something like:
> 
> let a = random.draw(from: list)

But now the RNG has to understand the concept of collections. I would argue it 
is much cleaner to write an extension on Collection.

func randomElement(using source: RandomSource = .default) -> Element? {
guard !isEmpty else {return nil}
let idx = Int.random(in: 0…(count - 1), using: source)
return self[idx]
}

> 
>> let b:Int? = list.popRandomElement //Now list contains all the elements 
>> except the one in ‚b’
> 
> we already have remove(at:), this can be used trivially:
> 
> let b = list.remove(at: random.draw(from: list.indices))
> 
> a little bit more verbose, but easily understandable.
> It uses well known building blocks and does not increase the API surface of 
> collections.

True.  But you could make the same argument for popLast().

I think both are common enough use-cases that they warrant the convenience 
method.  If not though, I can just add it myself for my own code.

Thanks,
Jon


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


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

2017-11-30 Thread TellowKrinkle via swift-evolution
doesn't need to be of the same type as other 
>> RNGs, conform to the same protocols, or for that matter, does not even need 
>> to be a type or be written in Swift.
> 
> I have also implemented some version of these APIs, both for Random and 
> RepeatablyRandom sources.
> 
> I get what you are saying about just being able to use the constructs from 
> Int, etc…, but we still need a public default.  Let me give a concrete 
> example of CGSize.  Yes, we want to just use CGFloat’s random, but if we 
> don’t have a publicly available way to call the default then we have to 
> implement the same algorithm twice, which is problematic. (Code written in 
> Mail)
> 
> static func random(width widthRange: ClosedRange, height 
> heightRange: ClosedRange, using source: RandomSource = .default) -> 
> CGSize {
>   let w = CGFloat.random(in: widthRange, using: source)
>   let h = CGFloat.random(in: heightRange, using: source)
>   return CGSize(width: w, height: h)
> }
> 
> Without the default I would have to have a second version which used 
> CGFloat(in:) in order to use the default source/generator, which means I 
> would have to update both places when I make changes.  Much better to just 
> allow a default value for ‘using:'.
> 
> Ah, this is assuming that one thinks it is a good idea to have `using:` 
> variants. Firstly, I'm not entirely sold on them. But let's suppose you've 
> convinced me. The example above illustrates a huge footgun:
> 
> Why do people want to use a different RNG? A very common reason: to obtain a 
> different distribution of random values. Now, can you simply perform 
> memberwise initialization as you show above and obtain a final instance of 
> the desired distribution simply because the stored properties are drawn from 
> that distribution? No no no no no! This implementation is incorrect.
> 
> Not only is it not _problematic_ to require two distinct implementations, 
> it's almost certainly required if you want to have any hope of implementing 
> them correctly.
>> 
>> 👍 
>> 
>>> 
>>> Thanks,
>>> Jon
>>> 
>>> 
>>>> On Nov 27, 2017, at 10:14 AM, TellowKrinkle via swift-evolution 
>>>> mailto:swift-evolution@swift.org>> wrote:
>>>> 
>>>> You say that all the `.random`s have different semantics, but to me (at 
>>>> least), they are all very similar.  All the methods can be summarized as 
>>>> selecting a single random element from a collection
>>>> `[0, 2, 3].random` selects a single element from the given collection
>>>> `Int.random(in: 0…8)` selects a single element from the given range
>>>> `Int.random` has no range, but selects a single element from the 
>>>> collection of all ints (equivalent to if the above method had a default 
>>>> value for its range)
>>>> So to me these are all doing the same operation, just with different types 
>>>> of inputs
>>>> 
>>>>> 2017/11/24 20:07、Alejandro Alonso >>>> <mailto:aalonso...@outlook.com>>のメール:
>>>>> 
>>>>> 
>>>>> - Alejandro
>>>>> 
>>>>> -- Forwarded message --
>>>>> From: Xiaodi Wu mailto:xiaodi...@gmail.com>>
>>>>> Date: Nov 24, 2017, 3:05 PM -0600
>>>>> To: Alejandro Alonso >>>> <mailto:aalonso...@outlook.com>>
>>>>> Cc: Brent Royal-Gordon >>>> <mailto:br...@architechies.com>>, Steve Canon via swift-evolution 
>>>>> mailto:swift-evolution@swift.org>>
>>>>> Subject: Re: [swift-evolution] [Proposal] Random Unification
>>>>> 
>>>>>> On Fri, Nov 24, 2017 at 2:55 PM, Alejandro Alonso 
>>>>>> mailto:aalonso...@outlook.com>> wrote:
>>>>>> 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 must disagree quite strongly here. The various facilities you name 
>>>>>> "random" have different semantics, and differences in semantics should 
>>>>>> be reflected in differences in names. It doesn't matter that some people 
>>>>>> don't find it confusi

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

2017-11-30 Thread Xiaodi Wu via swift-evolution
mplement the same algorithm twice, which is problematic. (Code written in
> Mail)
>
> static func random(width widthRange: ClosedRange, height
> heightRange: ClosedRange, using source: RandomSource = .default)
> -> CGSize {
> let w = CGFloat.random(in: widthRange, using: source)
> let h = CGFloat.random(in: heightRange, using: source)
> return CGSize(width: w, height: h)
> }
>
> Without the default I would have to have a second version which used
> CGFloat(in:) in order to use the default source/generator, which means I
> would have to update both places when I make changes.  Much better to just
> allow a default value for ‘using:'.
>

Ah, this is assuming that one thinks it is a good idea to have `using:`
variants. Firstly, I'm not entirely sold on them. But let's suppose you've
convinced me. The example above illustrates a huge footgun:

Why do people want to use a different RNG? A very common reason: to obtain
a different distribution of random values. Now, can you simply perform
memberwise initialization as you show above and obtain a final instance of
the desired distribution simply because the stored properties are drawn
from that distribution? No no no no no! This implementation is incorrect.

Not only is it not _problematic_ to require two distinct implementations,
it's almost certainly required if you want to have any hope of implementing
them correctly.

>
> 👍
>>
>>
>> Thanks,
>> Jon
>>
>>
>> On Nov 27, 2017, at 10:14 AM, TellowKrinkle via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>> You say that all the `.random`s have different semantics, but to me (at
>> least), they are all very similar.  All the methods can be summarized as
>> selecting a single random element from a collection
>> `[0, 2, 3].random` selects a single element from the given collection
>> `Int.random(in: 0…8)` selects a single element from the given range
>> `Int.random` has no range, but selects a single element from the
>> collection of all ints (equivalent to if the above method had a default
>> value for its range)
>> So to me these are all doing the same operation, just with different
>> types of inputs
>>
>> 2017/11/24 20:07、Alejandro Alonso のメール:
>>
>>
>> - Alejandro
>>
>> -- Forwarded message --
>> *From:* Xiaodi Wu 
>> *Date:* Nov 24, 2017, 3:05 PM -0600
>> *To:* Alejandro Alonso 
>> *Cc:* Brent Royal-Gordon , Steve Canon via
>> swift-evolution 
>> *Subject:* Re: [swift-evolution] [Proposal] Random Unification
>>
>> On Fri, Nov 24, 2017 at 2:55 PM, Alejandro Alonso > > wrote:
>>
>>> 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 must disagree quite strongly here. The various facilities you name
>> "random" have different semantics, and differences in semantics should be
>> reflected in differences in names. It doesn't matter that some people don't
>> find it confusing; it is objectively the case that you have named multiple
>> distinct facilities with the same name, which leads to confusion. I, for
>> one, get confused, and you can see on this list that people are using
>> arguments about one property named "random" to discuss another property
>> named "random". This is quite an intolerable situation.
>>
>> 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"
>>>
>>
>> "Sampling" is fine.
>>
>>
>> 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 pr

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

2017-11-30 Thread Dave DeLong via swift-evolution


> On Nov 30, 2017, at 5:02 PM, Jonathan Hull  wrote:
> 
> 
>> On Nov 30, 2017, at 3:52 PM, Dave DeLong > > wrote:
>> 
>> What is the useful distinction between generating a random value, and 
>> choosing a random element from a collection of all possible values?
> 
> I don’t have to generate (or keep in memory) that collection.  
> 
> I gave an example before of an easy to add API for random colors which allow 
> their saturation, lightness, and alpha to be fixed.  I use something very 
> similar all the time in some graphics code I have (varying only the hue or 
> saturation).  I also do the same with Sizes and CGVectors.  How would you 
> represent that as a collection to choose an element from?

You’re not picking a random color. You’re picking a random hue or a random 
saturation, and then constructing a color based off that. In other words, 
you’re choosing a value from 0…1:

let color = UIColor(hue: (0…1.0).random(), saturation: knownSaturationValue, 
brightness: knownBrightnessValue, alpha: knownAlphaValue)

Dave

> Also, for most of my use cases, I *need* to be able to plug in a repeatably 
> random source… otherwise pixels will start jumping around the screen when 
> people resize things.

That’s cool; I’m totally in favor of the RandomSource API as a way to model 
different distributions or algorithms or whatever. I just don’t thing 
“Foo.random” is a good idea.

Cheers

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


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

2017-11-30 Thread Jonathan Hull via swift-evolution

> On Nov 30, 2017, at 3:52 PM, Dave DeLong  wrote:
> 
> What is the useful distinction between generating a random value, and 
> choosing a random element from a collection of all possible values?

I don’t have to generate (or keep in memory) that collection.  

I gave an example before of an easy to add API for random colors which allow 
their saturation, lightness, and alpha to be fixed.  I use something very 
similar all the time in some graphics code I have (varying only the hue or 
saturation).  I also do the same with Sizes and CGVectors.  How would you 
represent that as a collection to choose an element from?

Also, for most of my use cases, I *need* to be able to plug in a repeatably 
random source… otherwise pixels will start jumping around the screen when 
people resize things.

Thanks,
Jon___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2017-11-30 Thread Martin Waitz via swift-evolution
Hi,

>>> This is redundant. In order to pick a random element, you’re saying I 
>>> should have to do “Int.random(0 ..< 10)”? The redundancy here is that I 
>>> have to specify Int twice: once for the “.random” call, and again for the 
>>> type of the range. We can do better than that.
> 
> I don’t see how this is redundant—do you mean that you’d need to write out 
> the type name instead of writing `(0..<10).random()!`? I continue to be of 
> the opinion that picking a random integer/floating-point value/Boolean and 
> picking a random element from a collection are two different operations.

Well, I don‘t see a big difference beteeen ranges and collections here. We can 
support both with the same syntax:

let a = random.draw(from: 1...3)
let b = random.draw(from: [1, 2, 3])

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


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

2017-11-30 Thread Dave DeLong via swift-evolution


> On Nov 30, 2017, at 4:46 PM, Jonathan Hull  wrote:
> 
>> 
>> On Nov 30, 2017, at 3:19 PM, Dave DeLong > > wrote:
>> 
>> 
>> 
>>> On Nov 30, 2017, at 4:08 PM, Jonathan Hull >> > wrote:
>>> 
>>> 
 On Nov 30, 2017, at 1:58 PM, Dave DeLong >>> > wrote:
 
 
 
> On Nov 30, 2017, at 2:48 PM, Jonathan Hull via swift-evolution 
> mailto:swift-evolution@swift.org>> wrote:
> 
> I would personally go with:
> 
>   Int.random //Returns a random Int
 
 “Type.random” is so rarely used as to not be worth the addition, IMO. If 
 you really need a random element from the *entire* domain, then I think 
 you should have to manually create the ClosedRange yourself.
>>> 
>>> What evidence do you have that this will not be used often?  There are many 
>>> types which aren’t comparable, and thus can’t have a ClosedRange.  Bool, 
>>> for example, would definitely require Bool.Random.  I certainly use the 
>>> full range of UInt and UInt8 on a regular basis (less so with Int).
>> 
>> Bool doesn’t necessarily need “Bool.random”. You just just as easily do 
>> “[true, false].random()”
> 
> I suppose you can do that, but [true, false].randomElement() is much less 
> efficient than Bool.random().  You are creating an array each time you need a 
> Bool, which in some of my use-cases, is pretty often.

So… keep the array around in memory so you don’t have to recreate it… 

> 
> 
>> As for evidence… my own experience. Other than small-value types (like 
>> Bool), it is *exceptionally* rare to come across a situation where you need 
>> a random from the entire range. Random colors  are interesting, but are rare 
>> because they can’t guarantee design aesthetic. Random Dates are nonsensical. 
>> Random Ints are maybe useful, but again, you almost always need a random Int 
>> from a range of possible values.
> 
> The fact that you haven’t needed it in your personal use cases isn’t evidence 
> that others don’t need it.

Yes, of course. But no where on this thread have I seen a compelling example of 
generating a random value from all possible values. Have I missed one?

> 
> 
>>> I think it is important to have Type.random as the base because there are 
>>> many types which would conform (not just Int & Double).  For example, I 
>>> might have an enum which returns a random case from MyEnum.random.  How 
>>> would you do that if random(in:) was the required base?
>> 
>> I actually don’t think there should be a static “random()” method. I think 
>> it should be a member function, not a type function.
> 
> I don’t understand this.  What would 1.random() do?

Well, if such an API existed, it would return “1”. However, since “1” isn’t a 
collection or range or whatever, this API wouldn’t even exist.

> 
> 
>> As for picking a random enum, see the previous bit about picking a random 
>> bool. And that will get even easier once we get the patch where enums have a 
>> static value listing all their cases, such as “CardSuits.allValues.random()”.
> 
> This would use .randomElement().  I think it is important to have a different 
> name for generating a random value and picking a random element from a 
> collection to avoid conflating the two.

What is the useful distinction between generating a random value, and choosing 
a random element from a collection of all possible values?

Dave

> 
> 
>   Int.random(in: ClosedRange) //Works for Comparable types. Gives a 
> result from the closed range. Closed Range is never empty.
 
 This is redundant. In order to pick a random element, you’re saying I 
 should have to do “Int.random(0 ..< 10)”? The redundancy here is that I 
 have to specify Int twice: once for the “.random” call, and again for the 
 type of the range. We can do better than that.
>>> 
>>> You didn’t have to specify it twice.  You used integer literals for the 
>>> range, which you could also do for Double or CGFloat.  Also, I am proposing 
>>> that we require a closed range, which would mean you would have to do 
>>> Int.random(0…9).  Otherwise we have to deal with ranges which are possibly 
>>> empty.
>> 
>> “0…9.random()” makes more sense to me than “Int.random(in: 0…9)". It makes 
>> it easier to change the type, and it doesn’t require me to know a priori the 
>> type of the range I’m dealing with.
> 
> 
> I think you could have both Int.random(in: 0…9) and (0…9).randomElement() 
> without issue.  You could even argue for conditionally conforming ranges and 
> allowing (0…9).random(), though it might be a harder sell.
> 
> Note that Int.random(in:) returns an ‘Int', and Range.randomElement() 
> returns an ‘Int?'
> 
> Thanks,
> Jon

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


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

2017-11-30 Thread Jonathan Hull via swift-evolution

> On Nov 30, 2017, at 3:19 PM, Dave DeLong  wrote:
> 
> 
> 
>> On Nov 30, 2017, at 4:08 PM, Jonathan Hull > > wrote:
>> 
>> 
>>> On Nov 30, 2017, at 1:58 PM, Dave DeLong >> > wrote:
>>> 
>>> 
>>> 
 On Nov 30, 2017, at 2:48 PM, Jonathan Hull via swift-evolution 
 mailto:swift-evolution@swift.org>> wrote:
 
 I would personally go with:
 
Int.random //Returns a random Int
>>> 
>>> “Type.random” is so rarely used as to not be worth the addition, IMO. If 
>>> you really need a random element from the *entire* domain, then I think you 
>>> should have to manually create the ClosedRange yourself.
>> 
>> What evidence do you have that this will not be used often?  There are many 
>> types which aren’t comparable, and thus can’t have a ClosedRange.  Bool, for 
>> example, would definitely require Bool.Random.  I certainly use the full 
>> range of UInt and UInt8 on a regular basis (less so with Int).
> 
> Bool doesn’t necessarily need “Bool.random”. You just just as easily do 
> “[true, false].random()”

I suppose you can do that, but [true, false].randomElement() is much less 
efficient than Bool.random().  You are creating an array each time you need a 
Bool, which in some of my use-cases, is pretty often.


> As for evidence… my own experience. Other than small-value types (like Bool), 
> it is *exceptionally* rare to come across a situation where you need a random 
> from the entire range. Random colors  are interesting, but are rare because 
> they can’t guarantee design aesthetic. Random Dates are nonsensical. Random 
> Ints are maybe useful, but again, you almost always need a random Int from a 
> range of possible values.

The fact that you haven’t needed it in your personal use cases isn’t evidence 
that others don’t need it.


>> I think it is important to have Type.random as the base because there are 
>> many types which would conform (not just Int & Double).  For example, I 
>> might have an enum which returns a random case from MyEnum.random.  How 
>> would you do that if random(in:) was the required base?
> 
> I actually don’t think there should be a static “random()” method. I think it 
> should be a member function, not a type function.

I don’t understand this.  What would 1.random() do?


> As for picking a random enum, see the previous bit about picking a random 
> bool. And that will get even easier once we get the patch where enums have a 
> static value listing all their cases, such as “CardSuits.allValues.random()”.

This would use .randomElement().  I think it is important to have a different 
name for generating a random value and picking a random element from a 
collection to avoid conflating the two.


Int.random(in: ClosedRange) //Works for Comparable types. Gives a 
 result from the closed range. Closed Range is never empty.
>>> 
>>> This is redundant. In order to pick a random element, you’re saying I 
>>> should have to do “Int.random(0 ..< 10)”? The redundancy here is that I 
>>> have to specify Int twice: once for the “.random” call, and again for the 
>>> type of the range. We can do better than that.
>> 
>> You didn’t have to specify it twice.  You used integer literals for the 
>> range, which you could also do for Double or CGFloat.  Also, I am proposing 
>> that we require a closed range, which would mean you would have to do 
>> Int.random(0…9).  Otherwise we have to deal with ranges which are possibly 
>> empty.
> 
> “0…9.random()” makes more sense to me than “Int.random(in: 0…9)". It makes it 
> easier to change the type, and it doesn’t require me to know a priori the 
> type of the range I’m dealing with.


I think you could have both Int.random(in: 0…9) and (0…9).randomElement() 
without issue.  You could even argue for conditionally conforming ranges and 
allowing (0…9).random(), though it might be a harder sell.

Note that Int.random(in:) returns an ‘Int', and Range.randomElement() 
returns an ‘Int?'

Thanks,
Jon



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


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

2017-11-30 Thread Martin Waitz via swift-evolution
Hello Jonathan,

> For collections, I think we should call returning a random element 
> -randomElement, and choosing a random element without replacement 
> -popRandomElement

I disagree because I don’t think that the random data is a property of the 
collection.
The collection is not the subject which has random elements, it’s more the 
object which is used when drawing an element.

> var list = [1,2,3,4]
> let a:Int? = list.randomElement //List is still [1,2,3,4] and ‘a’ contains 
> one of the elements

Instead I would prefer to have something like:

let a = random.draw(from: list)

> let b:Int? = list.popRandomElement //Now list contains all the elements 
> except the one in ‚b’

we already have remove(at:), this can be used trivially:

let b = list.remove(at: random.draw(from: list.indices))

a little bit more verbose, but easily understandable.
It uses well known building blocks and does not increase the API surface of 
collections.

— Martin

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


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

2017-11-30 Thread TellowKrinkle via swift-evolution
Don’t forget that if you already know the type, you can leave out the type 
name, so for example, to supply a random bool a function, you could just use 
`.random()` instead of `Bool.random()`, which removes a lot of the extra 
redundant type names.

> 2017/11/30 17:19、Dave DeLong のメール:
> 
> 
> 
>> On Nov 30, 2017, at 4:08 PM, Jonathan Hull > > wrote:
>> 
>> 
>>> On Nov 30, 2017, at 1:58 PM, Dave DeLong >> > wrote:
>>> 
>>> 
>>> 
 On Nov 30, 2017, at 2:48 PM, Jonathan Hull via swift-evolution 
 mailto:swift-evolution@swift.org>> wrote:
 
 I would personally go with:
 
Int.random //Returns a random Int
>>> 
>>> “Type.random” is so rarely used as to not be worth the addition, IMO. If 
>>> you really need a random element from the *entire* domain, then I think you 
>>> should have to manually create the ClosedRange yourself.
>> 
>> What evidence do you have that this will not be used often?  There are many 
>> types which aren’t comparable, and thus can’t have a ClosedRange.  Bool, for 
>> example, would definitely require Bool.Random.  I certainly use the full 
>> range of UInt and UInt8 on a regular basis (less so with Int).
> 
> Bool doesn’t necessarily need “Bool.random”. You just just as easily do 
> “[true, false].random()”
> 
> As for evidence… my own experience. Other than small-value types (like Bool), 
> it is *exceptionally* rare to come across a situation where you need a random 
> from the entire range. Random colors  are interesting, but are rare because 
> they can’t guarantee design aesthetic. Random Dates are nonsensical. Random 
> Ints are maybe useful, but again, you almost always need a random Int from a 
> range of possible values.
> 
>> 
>> I think it is important to have Type.random as the base because there are 
>> many types which would conform (not just Int & Double).  For example, I 
>> might have an enum which returns a random case from MyEnum.random.  How 
>> would you do that if random(in:) was the required base?
> 
> I actually don’t think there should be a static “random()” method. I think it 
> should be a member function, not a type function.
> 
> As for picking a random enum, see the previous bit about picking a random 
> bool. And that will get even easier once we get the patch where enums have a 
> static value listing all their cases, such as “CardSuits.allValues.random()”.
> 
>> 
>> 
>>> 
Int.random(in: ClosedRange) //Works for Comparable types. Gives a 
 result from the closed range. Closed Range is never empty.
>>> 
>>> This is redundant. In order to pick a random element, you’re saying I 
>>> should have to do “Int.random(0 ..< 10)”? The redundancy here is that I 
>>> have to specify Int twice: once for the “.random” call, and again for the 
>>> type of the range. We can do better than that.
>> 
>> You didn’t have to specify it twice.  You used integer literals for the 
>> range, which you could also do for Double or CGFloat.  Also, I am proposing 
>> that we require a closed range, which would mean you would have to do 
>> Int.random(0…9).  Otherwise we have to deal with ranges which are possibly 
>> empty.
> 
> “0…9.random()” makes more sense to me than “Int.random(in: 0…9)". It makes it 
> easier to change the type, and it doesn’t require me to know a priori the 
> type of the range I’m dealing with.
> 
> Dave

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


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

2017-11-30 Thread Jonathan Hull via swift-evolution
)

static func random(width widthRange: ClosedRange, height heightRange: 
ClosedRange, using source: RandomSource = .default) -> CGSize {
let w = CGFloat.random(in: widthRange, using: source)
let h = CGFloat.random(in: heightRange, using: source)
return CGSize(width: w, height: h)
}

Without the default I would have to have a second version which used 
CGFloat(in:) in order to use the default source/generator, which means I would 
have to update both places when I make changes.  Much better to just allow a 
default value for ‘using:'.

Thanks,
Jon

> 
> 
> 👍 
> 
>> 
>> Thanks,
>> Jon
>> 
>> 
>>> On Nov 27, 2017, at 10:14 AM, TellowKrinkle via swift-evolution 
>>> mailto:swift-evolution@swift.org>> wrote:
>>> 
>>> You say that all the `.random`s have different semantics, but to me (at 
>>> least), they are all very similar.  All the methods can be summarized as 
>>> selecting a single random element from a collection
>>> `[0, 2, 3].random` selects a single element from the given collection
>>> `Int.random(in: 0…8)` selects a single element from the given range
>>> `Int.random` has no range, but selects a single element from the collection 
>>> of all ints (equivalent to if the above method had a default value for its 
>>> range)
>>> So to me these are all doing the same operation, just with different types 
>>> of inputs
>>> 
>>>> 2017/11/24 20:07、Alejandro Alonso >>> <mailto:aalonso...@outlook.com>>のメール:
>>>> 
>>>> 
>>>> - Alejandro
>>>> 
>>>> -- Forwarded message --
>>>> From: Xiaodi Wu mailto:xiaodi...@gmail.com>>
>>>> Date: Nov 24, 2017, 3:05 PM -0600
>>>> To: Alejandro Alonso >>> <mailto:aalonso...@outlook.com>>
>>>> Cc: Brent Royal-Gordon >>> <mailto:br...@architechies.com>>, Steve Canon via swift-evolution 
>>>> mailto:swift-evolution@swift.org>>
>>>> Subject: Re: [swift-evolution] [Proposal] Random Unification
>>>> 
>>>>> On Fri, Nov 24, 2017 at 2:55 PM, Alejandro Alonso >>>> <mailto:aalonso...@outlook.com>> wrote:
>>>>> 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 must disagree quite strongly here. The various facilities you name 
>>>>> "random" have different semantics, and differences in semantics should be 
>>>>> reflected in differences in names. It doesn't matter that some people 
>>>>> don't find it confusing; it is objectively the case that you have named 
>>>>> multiple distinct facilities with the same name, which leads to 
>>>>> confusion. I, for one, get confused, and you can see on this list that 
>>>>> people are using arguments about one property named "random" to discuss 
>>>>> another property named "random". This is quite an intolerable situation.
>>>>> 
>>>>> 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"
>>>>> 
>>>>> "Sampling" is fine.
>>>>> 
>>>>> 
>>>>> On Nov 23, 2017, 12:54 AM -0600, Xiaodi Wu , wrote:
>>>>>> On Wed, Nov 22, 2017 at 23:01 Alejandro Alonso >>>>> <mailto:aalonso...@outlook.com>> 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 a

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

2017-11-30 Thread Nate Cook via swift-evolution
Swift.

Assuming we have two versions of whatever new random operations we add, where 
one takes an RNG as a parameter and the other uses the default, how would I add 
functionality that matches this pattern in my own code? The standard library 
would look have code like this:

extension MutableCollection {
func shuffle(using rng: RNG) {
// shuffle the elements
}

func shuffle() {
shuffle(using: _privateDefaultRNG)
}
}

Let’s say I’m writing something for my own app or library, and want to add two 
related methods with the same pattern:

extension Collection {
func randomRange(length: Int, using rng: RNG) -> [SubSequence] {
// select a starting point in 0.. 👍 
> 
>> 
>> Thanks,
>> Jon
>> 
>> 
>>> On Nov 27, 2017, at 10:14 AM, TellowKrinkle via swift-evolution 
>>> mailto:swift-evolution@swift.org>> wrote:
>>> 
>>> You say that all the `.random`s have different semantics, but to me (at 
>>> least), they are all very similar.  All the methods can be summarized as 
>>> selecting a single random element from a collection
>>> `[0, 2, 3].random` selects a single element from the given collection
>>> `Int.random(in: 0…8)` selects a single element from the given range
>>> `Int.random` has no range, but selects a single element from the collection 
>>> of all ints (equivalent to if the above method had a default value for its 
>>> range)
>>> So to me these are all doing the same operation, just with different types 
>>> of inputs
>>> 
>>>> 2017/11/24 20:07、Alejandro Alonso >>> <mailto:aalonso...@outlook.com>>のメール:
>>>> 
>>>> 
>>>> - Alejandro
>>>> 
>>>> -- Forwarded message --
>>>> From: Xiaodi Wu mailto:xiaodi...@gmail.com>>
>>>> Date: Nov 24, 2017, 3:05 PM -0600
>>>> To: Alejandro Alonso >>> <mailto:aalonso...@outlook.com>>
>>>> Cc: Brent Royal-Gordon >>> <mailto:br...@architechies.com>>, Steve Canon via swift-evolution 
>>>> mailto:swift-evolution@swift.org>>
>>>> Subject: Re: [swift-evolution] [Proposal] Random Unification
>>>> 
>>>>> On Fri, Nov 24, 2017 at 2:55 PM, Alejandro Alonso >>>> <mailto:aalonso...@outlook.com>> wrote:
>>>>> 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 must disagree quite strongly here. The various facilities you name 
>>>>> "random" have different semantics, and differences in semantics should be 
>>>>> reflected in differences in names. It doesn't matter that some people 
>>>>> don't find it confusing; it is objectively the case that you have named 
>>>>> multiple distinct facilities with the same name, which leads to 
>>>>> confusion. I, for one, get confused, and you can see on this list that 
>>>>> people are using arguments about one property named "random" to discuss 
>>>>> another property named "random". This is quite an intolerable situation.
>>>>> 
>>>>> 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"
>>>>> 
>>>>> "Sampling" is fine.
>>>>> 
>>>>> 
>>>>> On Nov 23, 2017, 12:54 AM -0600, Xiaodi Wu , wrote:
>>>>>> On Wed, Nov 22, 2017 at 23:01 Alejandro Alonso >>>>> <mailto:aalonso...@outlook.com>> 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. 
>

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

2017-11-30 Thread Dave DeLong via swift-evolution


> On Nov 30, 2017, at 4:08 PM, Jonathan Hull  wrote:
> 
> 
>> On Nov 30, 2017, at 1:58 PM, Dave DeLong > > wrote:
>> 
>> 
>> 
>>> On Nov 30, 2017, at 2:48 PM, Jonathan Hull via swift-evolution 
>>> mailto:swift-evolution@swift.org>> wrote:
>>> 
>>> I would personally go with:
>>> 
>>> Int.random //Returns a random Int
>> 
>> “Type.random” is so rarely used as to not be worth the addition, IMO. If you 
>> really need a random element from the *entire* domain, then I think you 
>> should have to manually create the ClosedRange yourself.
> 
> What evidence do you have that this will not be used often?  There are many 
> types which aren’t comparable, and thus can’t have a ClosedRange.  Bool, for 
> example, would definitely require Bool.Random.  I certainly use the full 
> range of UInt and UInt8 on a regular basis (less so with Int).

Bool doesn’t necessarily need “Bool.random”. You just just as easily do “[true, 
false].random()”

As for evidence… my own experience. Other than small-value types (like Bool), 
it is *exceptionally* rare to come across a situation where you need a random 
from the entire range. Random colors  are interesting, but are rare because 
they can’t guarantee design aesthetic. Random Dates are nonsensical. Random 
Ints are maybe useful, but again, you almost always need a random Int from a 
range of possible values.

> 
> I think it is important to have Type.random as the base because there are 
> many types which would conform (not just Int & Double).  For example, I might 
> have an enum which returns a random case from MyEnum.random.  How would you 
> do that if random(in:) was the required base?

I actually don’t think there should be a static “random()” method. I think it 
should be a member function, not a type function.

As for picking a random enum, see the previous bit about picking a random bool. 
And that will get even easier once we get the patch where enums have a static 
value listing all their cases, such as “CardSuits.allValues.random()”.

> 
> 
>> 
>>> Int.random(in: ClosedRange) //Works for Comparable types. Gives a 
>>> result from the closed range. Closed Range is never empty.
>> 
>> This is redundant. In order to pick a random element, you’re saying I should 
>> have to do “Int.random(0 ..< 10)”? The redundancy here is that I have to 
>> specify Int twice: once for the “.random” call, and again for the type of 
>> the range. We can do better than that.
> 
> You didn’t have to specify it twice.  You used integer literals for the 
> range, which you could also do for Double or CGFloat.  Also, I am proposing 
> that we require a closed range, which would mean you would have to do 
> Int.random(0…9).  Otherwise we have to deal with ranges which are possibly 
> empty.

“0…9.random()” makes more sense to me than “Int.random(in: 0…9)". It makes it 
easier to change the type, and it doesn’t require me to know a priori the type 
of the range I’m dealing with.

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


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

2017-11-30 Thread Erica Sadun via swift-evolution
eed never be exposed publicly, and since its functions are strictly 
>> redundant to these other APIs (which, of course, are the "currency" APIs 
>> that our purpose here is to design and make public), the default random is 
>> required only for internal implementation of the "currency" APIs and (a) is 
>> better off *not* exposed; (b) doesn't need to be of the same type as other 
>> RNGs, conform to the same protocols, or for that matter, does not even need 
>> to be a type or be written in Swift.
>> 
>> 
>> 👍 
>> 
>>> 
>>> Thanks,
>>> Jon
>>> 
>>> 
>>>> On Nov 27, 2017, at 10:14 AM, TellowKrinkle via swift-evolution 
>>>> mailto:swift-evolution@swift.org>> wrote:
>>>> 
>>>> You say that all the `.random`s have different semantics, but to me (at 
>>>> least), they are all very similar.  All the methods can be summarized as 
>>>> selecting a single random element from a collection
>>>> `[0, 2, 3].random` selects a single element from the given collection
>>>> `Int.random(in: 0…8)` selects a single element from the given range
>>>> `Int.random` has no range, but selects a single element from the 
>>>> collection of all ints (equivalent to if the above method had a default 
>>>> value for its range)
>>>> So to me these are all doing the same operation, just with different types 
>>>> of inputs
>>>> 
>>>>> 2017/11/24 20:07、Alejandro Alonso >>>> <mailto:aalonso...@outlook.com>>のメール:
>>>>> 
>>>>> 
>>>>> - Alejandro
>>>>> 
>>>>> -- Forwarded message --
>>>>> From: Xiaodi Wu mailto:xiaodi...@gmail.com>>
>>>>> Date: Nov 24, 2017, 3:05 PM -0600
>>>>> To: Alejandro Alonso >>>> <mailto:aalonso...@outlook.com>>
>>>>> Cc: Brent Royal-Gordon >>>> <mailto:br...@architechies.com>>, Steve Canon via swift-evolution 
>>>>> mailto:swift-evolution@swift.org>>
>>>>> Subject: Re: [swift-evolution] [Proposal] Random Unification
>>>>> 
>>>>>> On Fri, Nov 24, 2017 at 2:55 PM, Alejandro Alonso 
>>>>>> mailto:aalonso...@outlook.com>> wrote:
>>>>>> 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 must disagree quite strongly here. The various facilities you name 
>>>>>> "random" have different semantics, and differences in semantics should 
>>>>>> be reflected in differences in names. It doesn't matter that some people 
>>>>>> don't find it confusing; it is objectively the case that you have named 
>>>>>> multiple distinct facilities with the same name, which leads to 
>>>>>> confusion. I, for one, get confused, and you can see on this list that 
>>>>>> people are using arguments about one property named "random" to discuss 
>>>>>> another property named "random". This is quite an intolerable situation.
>>>>>> 
>>>>>> 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"
>>>>>> 
>>>>>> "Sampling" is fine.
>>>>>> 
>>>>>> 
>>>>>> On Nov 23, 2017, 12:54 AM -0600, Xiaodi Wu , wrote:
>>>>>>> On Wed, Nov 22, 2017 at 23:01 Alejandro Alonso >>>>>> <mailto:aalonso...@outlook.com>> wrote:
>>>>>>> Like I’ve said, python has different syntax grammar. We have to read 
>>>>>>> each call site and for

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

2017-11-30 Thread Jonathan Hull via swift-evolution
 are strictly 
>> redundant to these other APIs (which, of course, are the "currency" APIs 
>> that our purpose here is to design and make public), the default random is 
>> required only for internal implementation of the "currency" APIs and (a) is 
>> better off *not* exposed; (b) doesn't need to be of the same type as other 
>> RNGs, conform to the same protocols, or for that matter, does not even need 
>> to be a type or be written in Swift.
>> 
>> 
>> 👍 
>> 
>>> 
>>> Thanks,
>>> Jon
>>> 
>>> 
>>>> On Nov 27, 2017, at 10:14 AM, TellowKrinkle via swift-evolution 
>>>> mailto:swift-evolution@swift.org>> wrote:
>>>> 
>>>> You say that all the `.random`s have different semantics, but to me (at 
>>>> least), they are all very similar.  All the methods can be summarized as 
>>>> selecting a single random element from a collection
>>>> `[0, 2, 3].random` selects a single element from the given collection
>>>> `Int.random(in: 0…8)` selects a single element from the given range
>>>> `Int.random` has no range, but selects a single element from the 
>>>> collection of all ints (equivalent to if the above method had a default 
>>>> value for its range)
>>>> So to me these are all doing the same operation, just with different types 
>>>> of inputs
>>>> 
>>>>> 2017/11/24 20:07、Alejandro Alonso >>>> <mailto:aalonso...@outlook.com>>のメール:
>>>>> 
>>>>> 
>>>>> - Alejandro
>>>>> 
>>>>> -- Forwarded message --
>>>>> From: Xiaodi Wu mailto:xiaodi...@gmail.com>>
>>>>> Date: Nov 24, 2017, 3:05 PM -0600
>>>>> To: Alejandro Alonso >>>> <mailto:aalonso...@outlook.com>>
>>>>> Cc: Brent Royal-Gordon >>>> <mailto:br...@architechies.com>>, Steve Canon via swift-evolution 
>>>>> mailto:swift-evolution@swift.org>>
>>>>> Subject: Re: [swift-evolution] [Proposal] Random Unification
>>>>> 
>>>>>> On Fri, Nov 24, 2017 at 2:55 PM, Alejandro Alonso 
>>>>>> mailto:aalonso...@outlook.com>> wrote:
>>>>>> 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 must disagree quite strongly here. The various facilities you name 
>>>>>> "random" have different semantics, and differences in semantics should 
>>>>>> be reflected in differences in names. It doesn't matter that some people 
>>>>>> don't find it confusing; it is objectively the case that you have named 
>>>>>> multiple distinct facilities with the same name, which leads to 
>>>>>> confusion. I, for one, get confused, and you can see on this list that 
>>>>>> people are using arguments about one property named "random" to discuss 
>>>>>> another property named "random". This is quite an intolerable situation.
>>>>>> 
>>>>>> 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"
>>>>>> 
>>>>>> "Sampling" is fine.
>>>>>> 
>>>>>> 
>>>>>> On Nov 23, 2017, 12:54 AM -0600, Xiaodi Wu , wrote:
>>>>>>> On Wed, Nov 22, 2017 at 23:01 Alejandro Alonso >>>>>> <mailto:aalonso...@outlook.com>> 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, 

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

2017-11-30 Thread Jonathan Hull via swift-evolution
quivalent to if the above method had a default value for its 
>>> range)
>>> So to me these are all doing the same operation, just with different types 
>>> of inputs
>>> 
>>>> 2017/11/24 20:07、Alejandro Alonso >>> <mailto:aalonso...@outlook.com>>のメール:
>>>> 
>>>> 
>>>> - Alejandro
>>>> 
>>>> -- Forwarded message --
>>>> From: Xiaodi Wu mailto:xiaodi...@gmail.com>>
>>>> Date: Nov 24, 2017, 3:05 PM -0600
>>>> To: Alejandro Alonso >>> <mailto:aalonso...@outlook.com>>
>>>> Cc: Brent Royal-Gordon >>> <mailto:br...@architechies.com>>, Steve Canon via swift-evolution 
>>>> mailto:swift-evolution@swift.org>>
>>>> Subject: Re: [swift-evolution] [Proposal] Random Unification
>>>> 
>>>>> On Fri, Nov 24, 2017 at 2:55 PM, Alejandro Alonso >>>> <mailto:aalonso...@outlook.com>> wrote:
>>>>> 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 must disagree quite strongly here. The various facilities you name 
>>>>> "random" have different semantics, and differences in semantics should be 
>>>>> reflected in differences in names. It doesn't matter that some people 
>>>>> don't find it confusing; it is objectively the case that you have named 
>>>>> multiple distinct facilities with the same name, which leads to 
>>>>> confusion. I, for one, get confused, and you can see on this list that 
>>>>> people are using arguments about one property named "random" to discuss 
>>>>> another property named "random". This is quite an intolerable situation.
>>>>> 
>>>>> 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"
>>>>> 
>>>>> "Sampling" is fine.
>>>>> 
>>>>> 
>>>>> On Nov 23, 2017, 12:54 AM -0600, Xiaodi Wu , wrote:
>>>>>> On Wed, Nov 22, 2017 at 23:01 Alejandro Alonso >>>>> <mailto:aalonso...@outlook.com>> 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 
>&g

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

2017-11-30 Thread TellowKrinkle via swift-evolution
t;>> mailto:swift-evolution@swift.org>> wrote:
>>> 
>>> You say that all the `.random`s have different semantics, but to me (at 
>>> least), they are all very similar.  All the methods can be summarized as 
>>> selecting a single random element from a collection
>>> `[0, 2, 3].random` selects a single element from the given collection
>>> `Int.random(in: 0…8)` selects a single element from the given range
>>> `Int.random` has no range, but selects a single element from the collection 
>>> of all ints (equivalent to if the above method had a default value for its 
>>> range)
>>> So to me these are all doing the same operation, just with different types 
>>> of inputs
>>> 
>>>> 2017/11/24 20:07、Alejandro Alonso >>> <mailto:aalonso...@outlook.com>>のメール:
>>>> 
>>>> 
>>>> - Alejandro
>>>> 
>>>> -- Forwarded message --
>>>> From: Xiaodi Wu mailto:xiaodi...@gmail.com>>
>>>> Date: Nov 24, 2017, 3:05 PM -0600
>>>> To: Alejandro Alonso >>> <mailto:aalonso...@outlook.com>>
>>>> Cc: Brent Royal-Gordon >>> <mailto:br...@architechies.com>>, Steve Canon via swift-evolution 
>>>> mailto:swift-evolution@swift.org>>
>>>> Subject: Re: [swift-evolution] [Proposal] Random Unification
>>>> 
>>>>> On Fri, Nov 24, 2017 at 2:55 PM, Alejandro Alonso >>>> <mailto:aalonso...@outlook.com>> wrote:
>>>>> 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 must disagree quite strongly here. The various facilities you name 
>>>>> "random" have different semantics, and differences in semantics should be 
>>>>> reflected in differences in names. It doesn't matter that some people 
>>>>> don't find it confusing; it is objectively the case that you have named 
>>>>> multiple distinct facilities with the same name, which leads to 
>>>>> confusion. I, for one, get confused, and you can see on this list that 
>>>>> people are using arguments about one property named "random" to discuss 
>>>>> another property named "random". This is quite an intolerable situation.
>>>>> 
>>>>> 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"
>>>>> 
>>>>> "Sampling" is fine.
>>>>> 
>>>>> 
>>>>> On Nov 23, 2017, 12:54 AM -0600, Xiaodi Wu , wrote:
>>>>>> On Wed, Nov 22, 2017 at 23:01 Alejandro Alonso >>>>> <mailto:aalonso...@outlook.com>> 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,

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

2017-11-30 Thread Xiaodi Wu via swift-evolution
On Thu, Nov 30, 2017 at 3:58 PM, Dave DeLong via swift-evolution <
swift-evolution@swift.org> wrote:

>
>
> On Nov 30, 2017, at 2:48 PM, Jonathan Hull via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> I would personally go with:
>
> Int.random //Returns a random Int
>
>
> “Type.random” is so rarely used as to not be worth the addition, IMO. If
> you really need a random element from the *entire* domain, then I think you
> should have to manually create the ClosedRange yourself.
>
> Int.random(in: ClosedRange) //Works for Comparable types. Gives a
> result from the closed range. Closed Range is never empty.
>
>
> This is redundant. In order to pick a random element, you’re saying I
> should have to do “Int.random(0 ..< 10)”? The redundancy here is that I
> have to specify Int twice: once for the “.random” call, and again for the
> type of the range. We can do better than that.
>
> [0,2,3].randomElement //Returns a random element from the collection
>
>
> I strongly believe this should be a method, not a property. Properties,
> like .first and .last, are expected to return the same value each time you
> access them. “.random” inherently breaks that.
>

FWIW--and this isn't a vote, I know--I largely agree with Dave DeLong's
conclusions above, and for substantially the same reasons.

>
> Then a version of each with a ‘using:’ parameter which takes a
> generator/source:
>
> Int.random(using: RandomSource) //Returns a random Int using the given
> source of randomness
> Int.random(in: ClosedRange, using: RandomSource)
> [0,2,3].randomElement(using: RandomSource)
>
> In my own RandomSource & RandomSourceCreatable protocols, I frequently use
> random colors and sizes as well.  The issue there is that you really want a
> closed range for each dimension. I wish Swift had a better notion of
> dimensionality baked into the language.
>
> What I ended up doing was having a “constraints” parameter which took an
> array of constraints which corresponded to various dimensions.  It works
> for me, but it might be a bit complex for something in the standard library.
>
> Honestly, given the current capabilities of Swift what this really calls
> for is custom initializers/functions for dimensional types:
>
> UIColor.random //This comes from the protocol
> UIColor.random(hue: ClosedRange = 0…1, saturation:
> ClosedRange = 0…1, brightness: ClosedRange = 0…1, alpha:
> ClosedRange = 1…1)
> //…and of course the same as above, but with ‘using:'
>
> Then you can easily get random colors which look like they belong together:
> let myColor = UIColor.random(saturation: 0.2…0.2, brightness: 0.6…0.6)
>
> There would probably also be a convenience version taking CGFloats and
> passing them to the real function as ranges:
>
> let myColor = UIColor.random(saturation: 0.2, brightness: 0.6)
>
>
> This means that our default RandomSource needs to be publicly available,
> so that the custom functions can use it as the default…
>
>
It does not. Having actually implemented some version of these APIs, it's
readily apparent now to me that all custom types can simply call
Int.random(in:) (or UnsafeRawBufferPointer.random(byteCount:), or
whatever else we want to have in the standard library) to get random values
from the default RNG for any built-in type and size. The actual default
random need never be exposed publicly, and since its functions are strictly
redundant to these other APIs (which, of course, are the "currency" APIs
that our purpose here is to design and make public), the default random is
required only for internal implementation of the "currency" APIs and (a) is
better off *not* exposed; (b) doesn't need to be of the same type as other
RNGs, conform to the same protocols, or for that matter, does not even need
to be a type or be written in Swift.


👍
>
>
> Thanks,
> Jon
>
>
> On Nov 27, 2017, at 10:14 AM, TellowKrinkle via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> You say that all the `.random`s have different semantics, but to me (at
> least), they are all very similar.  All the methods can be summarized as
> selecting a single random element from a collection
> `[0, 2, 3].random` selects a single element from the given collection
> `Int.random(in: 0…8)` selects a single element from the given range
> `Int.random` has no range, but selects a single element from the
> collection of all ints (equivalent to if the above method had a default
> value for its range)
> So to me these are all doing the same operation, just with different types
> of inputs
>
> 2017/11/24 20:07、Alejandro Alonso のメール:
>
>
> - Alejandro
>
> -- Forwarded message --
>

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

2017-11-30 Thread Dave DeLong via swift-evolution
On Nov 30, 2017, at 2:48 PM, Jonathan Hull via swift-evolution <swift-evolution@swift.org> wrote:I would personally go with:	Int.random //Returns a random Int“Type.random” is so rarely used as to not be worth the addition, IMO. If you really need a random element from the *entire* domain, then I think you should have to manually create the ClosedRange yourself.	Int.random(in: ClosedRange) //Works for Comparable types. Gives a result from the closed range. Closed Range is never empty.This is redundant. In order to pick a random element, you’re saying I should have to do “Int.random(0 ..< 10)”? The redundancy here is that I have to specify Int twice: once for the “.random” call, and again for the type of the range. We can do better than that.	[0,2,3].randomElement //Returns a random element from the collectionI strongly believe this should be a method, not a property. Properties, like .first and .last, are expected to return the same value each time you access them. “.random” inherently breaks that.Then a version of each with a ‘using:’ parameter which takes a generator/source:	Int.random(using: RandomSource) //Returns a random Int using the given source of randomness	Int.random(in: ClosedRange, using: RandomSource)	[0,2,3].randomElement(using: RandomSource)In my own RandomSource & RandomSourceCreatable protocols, I frequently use random colors and sizes as well.  The issue there is that you really want a closed range for each dimension. I wish Swift had a better notion of dimensionality baked into the language. What I ended up doing was having a “constraints” parameter which took an array of constraints which corresponded to various dimensions.  It works for me, but it might be a bit complex for something in the standard library.Honestly, given the current capabilities of Swift what this really calls for is custom initializers/functions for dimensional types:	UIColor.random //This comes from the protocol	UIColor.random(hue: ClosedRange = 0…1, saturation: ClosedRange = 0…1, brightness: ClosedRange = 0…1, alpha: ClosedRange = 1…1)	//…and of course the same as above, but with ‘using:'Then you can easily get random colors which look like they belong together:		let myColor = UIColor.random(saturation: 0.2…0.2, brightness: 0.6…0.6) There would probably also be a convenience version taking CGFloats and passing them to the real function as ranges:	let myColor = UIColor.random(saturation: 0.2, brightness: 0.6)This means that our default RandomSource needs to be publicly available, so that the custom functions can use it as the default…👍 Thanks,JonOn Nov 27, 2017, at 10:14 AM, TellowKrinkle via swift-evolution <swift-evolution@swift.org> wrote:You say that all the `.random`s have different semantics, but to me (at least), they are all very similar.  All the methods can be summarized as selecting a single random element from a collection`[0, 2, 3].random` selects a single element from the given collection`Int.random(in: 0…8)` selects a single element from the given range`Int.random` has no range, but selects a single element from the collection of all ints (equivalent to if the above method had a default value for its range)So to me these are all doing the same operation, just with different types of inputs2017/11/24 20:07、Alejandro Alonso <aalonso...@outlook.com>のメール:







- Alejandro


-- Forwarded message --
From: Xiaodi Wu <xiaodi...@gmail.com>
Date: Nov 24, 2017, 3:05 PM -0600
To: Alejandro Alonso <aalonso...@outlook.com>
Cc: Brent Royal-Gordon <br...@architechies.com>, Steve Canon via swift-evolution <swift-evolution@swift.org>
Subject: Re: [swift-evolution] [Proposal] Random Unification


On Fri, Nov 24, 2017 at 2:55 PM, Alejandro Alonso 
<aalonso...@outlook.com> wrote:





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 must disagree quite strongly here. The various facilities you name "random" have different semantics, and differences in semantics should be reflected in differences in names. It doesn't matter that some people don't find it confusing; it is objectively
 the case that you have named multiple distinct facilities with the same name, which leads to confusion. I, for one, get confused, and you can see on this list that people are using arguments about one property named "random" to discuss another property named
 "random". This is quite an intolerable situation.





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

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

2017-11-30 Thread Jonathan Hull via swift-evolution
For collections, I think we should call returning a random element 
-randomElement, and choosing a random element without replacement 
-popRandomElement

var list = [1,2,3,4]
let a:Int? = list.randomElement //List is still [1,2,3,4] and ‘a’ contains one 
of the elements
let b:Int? = list.popRandomElement //Now list contains all the elements except 
the one in ‘b’

Thanks,
Jon

> On Nov 30, 2017, at 10:15 AM, Xiaodi Wu via swift-evolution 
>  wrote:
> 
> Right—again, this is yet another difference between two things both named 
> “random” in this proposal. Almost always, when we say “give me two random 
> integers,” we want independent random samples from the set of all integers. 
> But for collections, a very common (and probably more common operation) is to 
> _sample without replacement_. Conflating the two is how hard-to-detect errors 
> arise.
> 
> On Thu, Nov 30, 2017 at 10:29 Martin Waitz via swift-evolution 
> mailto:swift-evolution@swift.org>> wrote:
> Hi Erica,
> 
> > Doesn't `choose` usually take two arguments, the `count` to choose 
> > (presumably defaulting to 1) and the collection to choose `from`?
> 
> This might be useful for collections, when you want to draw several elements 
> without drawing the same element twice.
> For ranges of random numbers you usually need independent numbers and just 
> call the generator multiple times.
> Both use cases could be provided as overloads (a default argument would 
> require that the return value has the same type, which would be unfortunate 
> here).
> 
> --
> Martin
> ___
> 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

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


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

2017-11-30 Thread Jonathan Hull via swift-evolution
I would personally go with:

Int.random //Returns a random Int
Int.random(in: ClosedRange) //Works for Comparable types. Gives a 
result from the closed range. Closed Range is never empty.
[0,2,3].randomElement //Returns a random element from the collection

Then a version of each with a ‘using:’ parameter which takes a generator/source:

Int.random(using: RandomSource) //Returns a random Int using the given 
source of randomness
Int.random(in: ClosedRange, using: RandomSource)
[0,2,3].randomElement(using: RandomSource)

In my own RandomSource & RandomSourceCreatable protocols, I frequently use 
random colors and sizes as well.  The issue there is that you really want a 
closed range for each dimension. I wish Swift had a better notion of 
dimensionality baked into the language. 

What I ended up doing was having a “constraints” parameter which took an array 
of constraints which corresponded to various dimensions.  It works for me, but 
it might be a bit complex for something in the standard library.

Honestly, given the current capabilities of Swift what this really calls for is 
custom initializers/functions for dimensional types:

UIColor.random //This comes from the protocol
UIColor.random(hue: ClosedRange = 0…1, saturation: 
ClosedRange = 0…1, brightness: ClosedRange = 0…1, alpha: 
ClosedRange = 1…1)
//…and of course the same as above, but with ‘using:'

Then you can easily get random colors which look like they belong together:

let myColor = UIColor.random(saturation: 0.2…0.2, brightness: 0.6…0.6) 

There would probably also be a convenience version taking CGFloats and passing 
them to the real function as ranges:

let myColor = UIColor.random(saturation: 0.2, brightness: 0.6)


This means that our default RandomSource needs to be publicly available, so 
that the custom functions can use it as the default...

Thanks,
Jon


> On Nov 27, 2017, at 10:14 AM, TellowKrinkle via swift-evolution 
>  wrote:
> 
> You say that all the `.random`s have different semantics, but to me (at 
> least), they are all very similar.  All the methods can be summarized as 
> selecting a single random element from a collection
> `[0, 2, 3].random` selects a single element from the given collection
> `Int.random(in: 0…8)` selects a single element from the given range
> `Int.random` has no range, but selects a single element from the collection 
> of all ints (equivalent to if the above method had a default value for its 
> range)
> So to me these are all doing the same operation, just with different types of 
> inputs
> 
>> 2017/11/24 20:07、Alejandro Alonso > <mailto:aalonso...@outlook.com>>のメール:
>> 
>> 
>> - Alejandro
>> 
>> -- Forwarded message --
>> From: Xiaodi Wu mailto:xiaodi...@gmail.com>>
>> Date: Nov 24, 2017, 3:05 PM -0600
>> To: Alejandro Alonso mailto:aalonso...@outlook.com>>
>> Cc: Brent Royal-Gordon > <mailto:br...@architechies.com>>, Steve Canon via swift-evolution 
>> mailto:swift-evolution@swift.org>>
>> Subject: Re: [swift-evolution] [Proposal] Random Unification
>> 
>>> On Fri, Nov 24, 2017 at 2:55 PM, Alejandro Alonso >> <mailto:aalonso...@outlook.com>> wrote:
>>> 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 must disagree quite strongly here. The various facilities you name 
>>> "random" have different semantics, and differences in semantics should be 
>>> reflected in differences in names. It doesn't matter that some people don't 
>>> find it confusing; it is objectively the case that you have named multiple 
>>> distinct facilities with the same name, which leads to confusion. I, for 
>>> one, get confused, and you can see on this list that people are using 
>>> arguments about one property named "random" to discuss another property 
>>> named "random". This is quite an intolerable situation.
>>> 
>>> 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”, 
>>> “

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

2017-11-30 Thread Xiaodi Wu via swift-evolution
Right—again, this is yet another difference between two things both named
“random” in this proposal. Almost always, when we say “give me two random
integers,” we want independent random samples from the set of all integers.
But for collections, a very common (and probably more common operation) is
to _sample without replacement_. Conflating the two is how hard-to-detect
errors arise.

On Thu, Nov 30, 2017 at 10:29 Martin Waitz via swift-evolution <
swift-evolution@swift.org> wrote:

> Hi Erica,
>
> > Doesn't `choose` usually take two arguments, the `count` to choose
> (presumably defaulting to 1) and the collection to choose `from`?
>
> This might be useful for collections, when you want to draw several
> elements without drawing the same element twice.
> For ranges of random numbers you usually need independent numbers and just
> call the generator multiple times.
> Both use cases could be provided as overloads (a default argument would
> require that the return value has the same type, which would be unfortunate
> here).
>
> --
> Martin
> ___
> 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-11-30 Thread Martin Waitz via swift-evolution
Hi Erica,

> Doesn't `choose` usually take two arguments, the `count` to choose 
> (presumably defaulting to 1) and the collection to choose `from`?

This might be useful for collections, when you want to draw several elements 
without drawing the same element twice.
For ranges of random numbers you usually need independent numbers and just call 
the generator multiple times.
Both use cases could be provided as overloads (a default argument would require 
that the return value has the same type, which would be unfortunate here).

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


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

2017-11-30 Thread Karl Wagner via swift-evolution


> On 28. Nov 2017, at 00:20, Martin Waitz via swift-evolution 
>  wrote:
> 
> Hello,
> 
>> 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)
> 
> I like this design a lot. After all, `random` is not a property of some type 
> or instance, but we want to generate a new random element within some 
> range/based on some given set.
> Modeling that as methods of the RNG seems to be much more natural.
> 
> -- 
> Martin
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

+1. This discussion seems to have been going on for a long time and I haven’t 
kept up with all of the arguments, but to me, “random” only makes sense when 
you’re talking about selecting something from a group.

Some data types, like Int and Bool, have a natural set of all discrete, allowed 
values, so there is some natural group to talk about which can serve as a 
reasonable default. Basically, they are similar to enums (remember the 
discussions we’ve been having about an “allCases” collection for enums? Is 
there possibly some unifying abstraction between these and types such as Int or 
Bool?). So I can only really see it looking more or less like this:

protocol RandomNumberGenerator {
func random(from: C) -> C.Element? where C: Collection
}

// I don’t know; there is probably a real compsci/maths/stats name for this. 
See ‘enum' discussion.

protocol ClosedValueSet {
static var allValues: AnyCollection { get } 
}

extension RandomNumberGenerator {
func random() -> T? where T: ClosedValueSet {
return random(from: T.allValues)
}
}

extension Int: ClosedValueSet {
static var allValues: AnyCollection { return 
AnyCollection(Int.min.. { return AnyCollection([true, 
false]) }
}

// …etc

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


  1   2   3   >