Re: [swift-evolution] FloatingPoint does not conform to ExpressibleByFloatLiteral

2018-01-17 Thread Jonathan Hull via swift-evolution
I’m with Nevin on this one.  Perhaps the easiest thing to do is to add 
something to the FloatLiteral type that lets you get it as a string if desired.

Didn’t we have a discussion a while back on how to make Integer Literals work 
with BigInt?  Maybe there is an idea from that discussion that would help.

Tl;dr:  Literals shouldn’t be tied to a particular implementation of a single 
conforming type (though they can/should be optimized for common 
implementations).  The issue here is that FloatLiteral is throwing out 
information which is given to it based on its underlying implementation.  I 
view this as a bug.

Thanks,
Jon

 
> On Jan 16, 2018, at 4:20 PM, Nevin Brackett-Rozinsky via swift-evolution 
>  wrote:
> 
> On Tue, Jan 16, 2018 at 6:31 PM, Xiaodi Wu  > wrote:
> On Tue, Jan 16, 2018 at 4:30 PM, Nevin Brackett-Rozinsky 
> > 
> wrote:
> The thing that is “broken” here is generic programming. If I constrain 
> something to FloatingPoint, I cannot use a float literal in calculations with 
> it:
> 
> func centimeters (inches: T) -> T {
> return 2.54 * inches// Error
> }
> 
> Why not constrain it to `BinaryFloatingPoint`? What other types are you 
> trying to use with this function?
> 
> We should not ask nor expect people to constrain their generic algorithms to 
> BinaryFloatingPoint unless they are working with the radix.
> 
>  
> so that eg. a Rational type could be used. And that gives a hint as to the 
> workaround:
> 
> func centimeters (inches: T) -> T {
> return (254 / 100) * inches
> }
> 
> Yes, you *could* do that.
> 
> And it seems I *will* be doing that, as long as such a workaround is 
> necessary. Though it does appear to have the unfortunate cost of an extra 
> division operation.
> 
> 
> That only works for numbers which don’t overflow the integer literals though.
> 
> Integer literals don't overflow until 2048 bits. The following compiles just 
> fine:
> 
> func moles(particles: T) -> T {
>   let N_A: T = 602_214_085_774_000_000_000_000
>   return particles / N_A
> }
> 
> When I write that in a playground it shows N_A as 1.67866967797794e+18.
> 
> (Also, you appear to have mistakenly concatenated the standard uncertainty in 
> the last 2 digits, “74”, onto the accepted value for the constant.)
> 
> 
> If we want a really large or small value then we have to split it in pieces:
> 
> func moles  (particles: T) -> T {
> let avogadroNumber: T = 6_022_140_857 * 100_000_000_000_000
> return particles / avogadroNumber
> }
> 
> It would be much nicer to write “let avogadroNumber: T = 6.022140857e23”.
> 
> You could write:
> 
> func moles(particles: T) -> T {
>   let N_A = T("6.02214085774e+23")!
>   return particles / N_A
> }
> 
> …or I could write “T: FloatingPoint & ExpressibleByFloatLiteral”. I could 
> even make a typealias for that. But I shouldn’t have to.
> 
> Nevin
> ___
> 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] [Pitch] Percentage Type

2018-01-16 Thread Jonathan Hull via swift-evolution
If you look at the implementation I provided, it allows for percentages higher 
than 100% (and has an easy way to clip them or map them to an arbitrary range).


> On Jan 16, 2018, at 11:39 AM, Dave DeLong via swift-evolution 
>  wrote:
> 
> 
> 
>> On Jan 16, 2018, at 9:56 AM, Jon Gilbert via swift-evolution 
>> > wrote:
>> 
>> No to this pitch, because a percentage can be higher than 100%.
> 
> ☝️ One need only look in Activity Monitor to see this in action.
> 
>> Use NumberFormatter to display a number as a percentage. 
>> https://developer.apple.com/documentation/foundation/numberformatter 
>> 
> I agree 1000%  
> 
>> Or you could make an NSNumber subclass if you want to enforce an arbitrary 
>> rule upon numbers.
> 
> In theory you can; in practice you can’t. Subclassing things like NSNumber is 
> fraught with undocumented peril.
> 
> Dave
> ___
> 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] [Pitch] Percentage Type

2018-01-16 Thread Jonathan Hull via swift-evolution
Mainly semantics.

We could technically use Int instead of having a Bool type (just using 1 and 
0).  We don’t do that since Int and Bool have intrinsically different meanings 
in code.  

What I am saying is that parameters that take the range 0 to 1 typically have a 
fundamentally different meaning (or at least a different way of thinking about 
them) than Doubles.  It would be nice to be able to see that distinction when 
using APIs.

With both this and the Angle type, I am pointing out areas where, due to 
historical reasons in C, we have conflated a bunch of types which have 
different behavior, and then just expect programmers to be conscientious enough 
to use them correctly in each case.  These types/numbers all have a different 
forms of dimensionality.

I’d like to discuss that before we lock everything down.

Thanks,
Jon

> On Jan 13, 2018, at 9:18 PM, Xiaodi Wu <xiaodi...@gmail.com> wrote:
> 
> As Erica mentioned about Angle, this seems to be a perfect fit for an 
> appropriately focused third-party library, but I'm not sure I appreciate why 
> this should be part of the standard library. In large part, you seem to have 
> reinvented a decimal type, which is already available in the form of 
> Foundation.Decimal on all supported platforms.
> 
> On Sat, Jan 13, 2018 at 9:07 PM, Jonathan Hull via swift-evolution 
> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
> Here is the code I use for percentage myself. (I incorrectly said I use a 
> UInt64… I use a UInt32):
> 
> ///Represents a percentage with the precision of millionths of 1 (i.e. 4 
> decimal places: XX.%). The value is always positive (or zero), but may be 
> greater than 100%
> struct Percentage {
> fileprivate(set) var millionths:UInt32
> 
> fileprivate init(storage:UInt32){
> millionths = storage
> }
> 
> static var quarter = Percentage(storage: 250_000)
> static var half= Percentage(storage: 500_000)
> static var threeQuarters = Percentage(storage: 750_000)
> static var full= Percentage(storage: 1_000_000)
> 
> init(millionths:Int) {
> self.millionths = UInt32(millionths)
> }
> 
> init(_ double:Double, range:ClosedRange = 0...1) {
> if range == 0...1 {
> self.millionths = UInt32(max(double * 1_000_000, 0))
> }else if range == 0...100{
> self.millionths = UInt32(max(double * 10_000, 0))
> }else{
> self.millionths = UInt32(max((double - 
> range.lowerBound)/(range.upperBound - range.lowerBound),0))
> }
> }
> 
> init(_ num:Num, range:ClosedRange = 0...1) {
> if range == 0...1 {
> self.millionths = UInt32(max(num * 1_000_000, 0).integerValue)
> }else if range == 0...100{
> self.millionths = UInt32(max(num * 10_000, 0).integerValue)
> }else{
> self.millionths = UInt32(max((num - 
> range.lowerBound)/(range.upperBound - range.lowerBound),0).integerValue)
> }
> }
> 
> init(_ decimal:Decimal, range:ClosedRange = 0...1) {
> if range == 0...1 {
> self.millionths = NSDecimalNumber(decimal: max(decimal * 
> 1_000_000, 0)).uint32Value
> }else if range == 0...100{
> self.millionths = NSDecimalNumber(decimal: max(decimal * 10_000, 
> 0)).uint32Value
> }else{
> let shifted = max((decimal - range.lowerBound)/(range.upperBound 
> - range.lowerBound),0)
> self.millionths = NSDecimalNumber(decimal: shifted).uint32Value
> }
> }
> 
> init(hundredths:Int) {
> self.millionths = UInt32(max(hundredths * 10_000, 0))
> }
> 
> init(thousandths:Int) {
> self.millionths = UInt32(max(thousandths * 1_000, 0))
> }
> 
> var isFull:Bool {
> return self.millionths >= 1_000_000
> }
> 
> var doubleValue:Double{
> return Double(self.millionths)/1_000_000
> }
> 
> var cgfloatValue:CGFloat{
> return CGFloat(self.millionths)/1_000_000
> }
> 
> var decimalValue:Decimal {
> return Decimal(self.millionths)/1_000_000
> }
> 
> var numValue:Num {
> return Num(numerator: Int32(self.millionths), denominator: 1_000_000)
> }
> 
> var hundredths:Int {
> return Int(self.millionths/10_000)
> }
> 
> var thousandths:Int {
> return Int(self.millionths/1_000)
> }
> 
> var tenThousandths:Int {
> return Int(self.millionths/100)
> }
> 
> func map(to range:ClosedRange) -> Num {
>

Re: [swift-evolution] [Pitch] Percentage Type

2018-01-13 Thread Jonathan Hull via swift-evolution
  
static func * (lhs:Percentage, rhs:Num)->Num {
return lhs.numValue * rhs
}

static func * (lhs:Num, rhs:Percentage)->Num {
return lhs * rhs.numValue
}

static func * (lhs:Percentage, rhs:Percentage)->Percentage {
return Percentage(lhs.decimalValue * rhs.decimalValue)
}

}


 
> On Jan 13, 2018, at 6:26 PM, Jonathan Hull via swift-evolution 
> <swift-evolution@swift.org> wrote:
> 
> Hi Evolution,
> 
> I was wondering if we would consider adding a percentage type to Swift.  This 
> would be a type with a value between 0 & 1.
> 
> I know we can and do use doubles or floats for this now, but there really is 
> a semantic difference between most parameters that take a value between 0 & 1 
> and those that take any floating point value.  It would be nice to have a 
> type that semantically means that the value is from 0 to 1.
> 
> It could even just wrap a Double for speed (in my own code I wrap a UInt64 
> for decimal accuracy… and to avoid issues around comparisons).
> 
> Thanks,
> Jon
> ___
> 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] [Pitch] Angle Type

2018-01-13 Thread Jonathan Hull via swift-evolution
Hi Evolution,

I would really like to see Swift gain an Angle type in the standard library.  
Every time I have to deal with an angle in an api, I have to go figure out the 
conventions for that call.  Is it in degrees? Is it in radians?  What if it is 
in radians, but I want to think about it in degrees?

I ended up writing an Angle type for my own code a few years back, and I have 
to say it is really wonderful.  It has greatly simplified my graphics work.  It 
takes a lot of mental load off of my brain when dealing with Angles.

I can of course initialize it either as degrees or radians (or revolutions), 
but I can also just say things like ‘.threeQuarterTurn’, and then I can get the 
value back out in whatever format I like.  There are also useful additions that 
let me normalize the angle to different ranges and which let me snap to the 
nearest multiple of an angle. Both of these are enormously useful for user 
facing features.  I can also do math on angles in a way that makes geometric 
sense for angles.  It is also really useful for interacting with CGVectors in 
intelligent ways.

Using Doubles or CGFloats to represent angles everywhere is just semantically 
wrong IMHO, and it stops us from adding all of these angle-specific niceties.

Happy to provide code if there is interest…

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


[swift-evolution] [Pitch] Percentage Type

2018-01-13 Thread Jonathan Hull via swift-evolution
Hi Evolution,

I was wondering if we would consider adding a percentage type to Swift.  This 
would be a type with a value between 0 & 1.

I know we can and do use doubles or floats for this now, but there really is a 
semantic difference between most parameters that take a value between 0 & 1 and 
those that take any floating point value.  It would be nice to have a type that 
semantically means that the value is from 0 to 1.

It could even just wrap a Double for speed (in my own code I wrap a UInt64 for 
decimal accuracy… and to avoid issues around comparisons).

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


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 <natec...@apple.com> wrote:
> 
> On Jan 12, 2018, at 6:24 PM, Jonathan Hull via swift-evolution 
> <swift-evolution@swift.org <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,
>

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, 

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

Re: [swift-evolution] Handling unknown cases in enums [RE: SE-0192]

2018-01-12 Thread Jonathan Hull via swift-evolution
I’m definitely in the error camp, but I will go along with a warning if 
everyone feels that is better.

Thanks,
Jon

> On Jan 12, 2018, at 3:08 PM, Jordan Rose via swift-evolution 
>  wrote:
> 
> Okay, I went back to `unknown case` in the proposal, but mentioned Chris's 
> point very specifically: if the compiler emits an error, we should go with 
> `case #unknown` instead. (I'm very strongly in the "warning" camp, though.)
> 
> I think the revised proposal is in good shape! 
> (https://github.com/apple/swift-evolution/pull/777) I think I've addressed 
> everyone's feedback either in the proposal or on-list, if not necessarily 
> convinced them. If there are no other major comments I'll let Ted know that 
> it's ready to re-run on Monday.
> 
> Jordan
> ___
> 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-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 
>> >, 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 

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 

Re: [swift-evolution] [Proposal] Revamp the playground quicklook APIs

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

> On Jan 11, 2018, at 11:22 AM, Connor Wakamo via swift-evolution 
>  wrote:
> 
> That’s very reasonable. I’ll update the proposal to use 
> CustomPlaygroundConvertible (unless I or someone else can come up with a 
> really good “Thing” for a name like CustomPlaygroundThingConvertible, as that 
> would even better match CustomStringConvertible/CustomDebugStringConvertible).

CustomPlaygroundPreviewConvertible?___
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:
> 
> 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 

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 

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-05 Thread Jonathan Hull via swift-evolution
Oh, I see… the case would silently change from unexpected to default if they 
were both included.  Hmm.  I will have to think on this more.

Thanks,
Jon

> On Jan 5, 2018, at 3:17 PM, Jordan Rose <jordan_r...@apple.com> wrote:
> 
> 
> 
>> On Jan 5, 2018, at 00:11, Jonathan Hull via swift-evolution 
>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>> 
>>> 
>>> On Jan 4, 2018, at 11:02 PM, Xiaodi Wu <xiaodi...@gmail.com 
>>> <mailto:xiaodi...@gmail.com>> wrote:
>>> 
>>> 
>>> On Fri, Jan 5, 2018 at 01:56 Jonathan Hull <jh...@gbis.com 
>>> <mailto:jh...@gbis.com>> wrote:
>>>> On Jan 4, 2018, at 10:31 PM, Xiaodi Wu via swift-evolution 
>>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>>> 
>>>> 
>>>> On Fri, Jan 5, 2018 at 00:21 Cheyo Jimenez <ch...@masters3d.com 
>>>> <mailto:ch...@masters3d.com>> wrote:
>>> 
>>>> 
>>>> On Jan 4, 2018, at 4:37 PM, Xiaodi Wu <xiaodi...@gmail.com 
>>>> <mailto:xiaodi...@gmail.com>> wrote:
>>>> 
>>> 
>>>>> On Thu, Jan 4, 2018 at 19:29 Cheyo J. Jimenez <ch...@masters3d.com 
>>>>> <mailto:ch...@masters3d.com>> wrote:
>>>>> 
>>>>> We seem to agree that, by virtue of not supporting use in a pattern and 
>>>>> being placed at the end, the feature is a flavor of default. I’m still 
>>>>> not sure I understand why you believe it should not be a flavor of 
>>>>> default going forward.
>>>>> 
>>>>>> 
>>>>>> You still haven’t answered my question, though—what’s the use case for 
>>>>>> the feature you propose?
>>>>> 
>>>>> My use case would be distinguishing between compile time known cases vs 
>>>>> “future only” cases (or unknown cases).
>>>>> 
>>>>> I understand that the feature you propose would allow you to make such a 
>>>>> distinction, but again, what is your use case for doing so?
>>> 
>>>> Breaking out early by checking unknown cases first. I admit this is not 
>>>> deal breaker, just a different style I’d like to see supported in the 
>>>> future. 
>>> 
>>>> 
>>>> I'm still not sure I understand. How can the machine know that it's 
>>>> dealing with an unknown case without first checking if it matches any 
>>>> known case?
>>> 
>>> 
>>> I had the same thought as Cheyo.  It isn’t a deal breaker… I like the 
>>> compromise, but I would prefer it trigger only on an actual unknown case 
>>> (as opposed to acting like default). I like to break failure cases out at 
>>> the top when possible. I don’t see any good reason not to support that 
>>> style.
>>> 
>>> To answer your question, in the naive sense, it basically is the same 
>>> question as asking if it is a known case (and then taking the inverse). 
>>> That doesn’t mean actually checking each case separately though. For 
>>> example, if the enum cases are internally represented as an unsigned 
>>> integer, and they are all together in a block, the compiler could simply 
>>> check that it is greater than the max known value. You could probably even 
>>> do a bit mask comparison in some cases...
>>> 
>>> These are obvious optimizations, but why does this require new syntax?
>> 
>> I am not sure I understand what you are asking. There isn’t additional 
>> syntax.  We are just arguing over the name + behavior of ‘unexpected:’.  You 
>> want it to behave like ‘default’ and I am saying that stops the use case I 
>> mention above.
>> 
>> 
>>> What do you gain from writing the unknown case first?
>> I know where to look for the failure cases.  I also tend put a bunch of 
>> guard statements near the beginning of a function.  It is just a programming 
>> style.
>> 
>> With my behavior of ‘unexpected:’ you can put it wherever you want.  Why 
>> limit that by forcing it to go at the end?
>> 
>>> Isn't this basically the same thing as asking for the ability to write the 
>>> default case first, a frequently suggested and rejected syntax addition?
>> 
>> No.  I don’t think I have ever heard that asked for, but putting default in 
>> a different place has a different meaning.  The way I read a switch 
>> statement anyway is that it

Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

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

> On Jan 4, 2018, at 11:02 PM, Xiaodi Wu  wrote:
> 
> 
> On Fri, Jan 5, 2018 at 01:56 Jonathan Hull  > wrote:
>> On Jan 4, 2018, at 10:31 PM, Xiaodi Wu via swift-evolution 
>> > wrote:
> 
>> 
>> On Fri, Jan 5, 2018 at 00:21 Cheyo Jimenez > > wrote:
> 
>> 
>> On Jan 4, 2018, at 4:37 PM, Xiaodi Wu > > wrote:
>> 
> 
>>> On Thu, Jan 4, 2018 at 19:29 Cheyo J. Jimenez >> > wrote:
>>> 
>>> We seem to agree that, by virtue of not supporting use in a pattern and 
>>> being placed at the end, the feature is a flavor of default. I’m still not 
>>> sure I understand why you believe it should not be a flavor of default 
>>> going forward.
>>> 
 
 You still haven’t answered my question, though—what’s the use case for the 
 feature you propose?
>>> 
>>> My use case would be distinguishing between compile time known cases vs 
>>> “future only” cases (or unknown cases).
>>> 
>>> I understand that the feature you propose would allow you to make such a 
>>> distinction, but again, what is your use case for doing so?
> 
>> Breaking out early by checking unknown cases first. I admit this is not deal 
>> breaker, just a different style I’d like to see supported in the future. 
> 
>> 
>> I'm still not sure I understand. How can the machine know that it's dealing 
>> with an unknown case without first checking if it matches any known case?
> 
> 
> I had the same thought as Cheyo.  It isn’t a deal breaker… I like the 
> compromise, but I would prefer it trigger only on an actual unknown case (as 
> opposed to acting like default). I like to break failure cases out at the top 
> when possible. I don’t see any good reason not to support that style.
> 
> To answer your question, in the naive sense, it basically is the same 
> question as asking if it is a known case (and then taking the inverse). That 
> doesn’t mean actually checking each case separately though. For example, if 
> the enum cases are internally represented as an unsigned integer, and they 
> are all together in a block, the compiler could simply check that it is 
> greater than the max known value. You could probably even do a bit mask 
> comparison in some cases...
> 
> These are obvious optimizations, but why does this require new syntax?

I am not sure I understand what you are asking. There isn’t additional syntax.  
We are just arguing over the name + behavior of ‘unexpected:’.  You want it to 
behave like ‘default’ and I am saying that stops the use case I mention above.


> What do you gain from writing the unknown case first?
I know where to look for the failure cases.  I also tend put a bunch of guard 
statements near the beginning of a function.  It is just a programming style.

With my behavior of ‘unexpected:’ you can put it wherever you want.  Why limit 
that by forcing it to go at the end?

> Isn't this basically the same thing as asking for the ability to write the 
> default case first, a frequently suggested and rejected syntax addition?

No.  I don’t think I have ever heard that asked for, but putting default in a 
different place has a different meaning.  The way I read a switch statement 
anyway is that it tries each case until it find one that matches.  Default 
matches everything, so it has to go at the end (since it will always match and 
nothing afterwards will be tried).

Having ‘unexpected:’ also match known/expected cases is problematic as a mental 
model.  I think that is just an artifact of the original proposal using 
default.  There is no reason 'unexpected:’ should have to handle known cases as 
well… let’s just have it trigger on unexpected ones.

Thanks,
Jon


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


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

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

> On Jan 4, 2018, at 10:31 PM, Xiaodi Wu via swift-evolution 
>  wrote:
> 
> On Fri, Jan 5, 2018 at 00:21 Cheyo Jimenez  > wrote:
> 
> On Jan 4, 2018, at 4:37 PM, Xiaodi Wu  > wrote:
> 
>> On Thu, Jan 4, 2018 at 19:29 Cheyo J. Jimenez > > wrote:
>> 
>> We seem to agree that, by virtue of not supporting use in a pattern and 
>> being placed at the end, the feature is a flavor of default. I’m still not 
>> sure I understand why you believe it should not be a flavor of default going 
>> forward.
>> 
>>> 
>>> You still haven’t answered my question, though—what’s the use case for the 
>>> feature you propose?
>> 
>> My use case would be distinguishing between compile time known cases vs 
>> “future only” cases (or unknown cases).
>> 
>> I understand that the feature you propose would allow you to make such a 
>> distinction, but again, what is your use case for doing so?
> 
> Breaking out early by checking unknown cases first. I admit this is not deal 
> breaker, just a different style I’d like to see supported in the future. 
> 
> I'm still not sure I understand. How can the machine know that it's dealing 
> with an unknown case without first checking if it matches any known case?

I had the same thought as Cheyo.  It isn’t a deal breaker… I like the 
compromise, but I would prefer it trigger only on an actual unknown case (as 
opposed to acting like default). I like to break failure cases out at the top 
when possible. I don’t see any good reason not to support that style.

To answer your question, in the naive sense, it basically is the same question 
as asking if it is a known case (and then taking the inverse). That doesn’t 
mean actually checking each case separately though. For example, if the enum 
cases are internally represented as an unsigned integer, and they are all 
together in a block, the compiler could simply check that it is greater than 
the max known value. You could probably even do a bit mask comparison in some 
cases...

If it is inefficient for some reason, the compiler should be free to rearrange 
the order of things, as long as it doesn’t change the outcome.

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


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-02 Thread Jonathan Hull via swift-evolution
I think there are a couple of different definitions running around, and that is 
confusing things.

In my mind, ‘unexpected:’ catches only cases which were unknown at compile 
time. Adding cases to an enum *should* be a source-breaking change. That is the 
whole point of this.  We should have to update the switch (either by handling 
new case explicitly, or by adding default) before successfully compiling.  What 
‘unexpected:’ protects against are changes to a linked binary (e.g. iOS) that 
are now vending cases we didn’t know about when we were compiled.

I’ll say it again… framing this idea as one of exhaustiveness is really 
confusing.  Enums should just always be exhaustive in swift.  There may be 
cases where we need to use ‘unexpected:’ to handle unexpected/future cases 
exhaustively.  If we annotate an enum as @frozen, then we won’t need to do that 
to be exhaustive because we know it won’t change out from under us.  Always 
exhaustive. Much less confusing…

Thanks,
Jon



> On Jan 2, 2018, at 1:41 PM, Xiaodi Wu via swift-evolution 
>  wrote:
> 
> On Tue, Jan 2, 2018 at 3:27 PM, Kevin Nattinger  > wrote:
> [...]
> 
>>> in what other circumstances do we insist that the compiler inform the end 
>>> user about future additions to the API at compile time?
>> 
>> This isn’t a request for the compiler to inform the user about future 
>> additions to an API.  It is a request to validate the compiler’s knowledge 
>> of the current state of an API with the current state of the source code. 
>> 
>> Well, it's of course impossible to inform the user about future additions, 
>> so that's poorly phrased on my part. It's about the compiler informing the 
>> end user about *new* additions, part of the *current* state of the API, that 
>> have cropped up since the user last revised the code when the API was in a 
>> *previous* state (or, indistinguishably, members of which a user is unaware 
>> regardless of the temporal sequence of when such members were added). In 
>> what other circumstances do we insist that the compiler perform this service?
> 
> Enums. That's literally how they work today. You are arguing in favor of 
> actively removing compiler-aided correctness.
> 
> There's also protocol requirements
> 
> No, that's now how enums work today, and it's not how protocol requirements 
> work today. Enums today are all semantically exhaustive; if a case is added 
> in a later version of a library, it's semantically a *different* enum type 
> that happens to share the same name. Not considering all the cases of an 
> exhaustive enum is an _error_, not a _warning_, because there is no basis on 
> which to proceed. This will not change with the proposal. Likewise, adding a 
> protocol requirement without a default implementation is source-breaking. The 
> result is a compiler _error_.
> 
> The question is, what non-source breaking API additions today cause the 
> compiler to inform the end user of such additions? The answer is: none 
> whatsoever. Not new methods or properties on a type, not even new protocol 
> requirements that have a default implementation.
> 
> 
> and, arguably, deprecated methods with a proper message ("use foo instead").
> 
> 
> ___
> 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] [Review] SE 0192 - Non-Exhaustive Enums

2018-01-02 Thread Jonathan Hull via swift-evolution
I think this is a good summary.  

I agree that we need to handle unexpected cases from changes to a binary 
somehow.  The main issue is that, when forcing developers to use ‘default’ to 
do it, it also brings along unwanted semantics that prevent warnings in the 
very common use case of a 3rd party library being updated.  The proposal is 
close to what we want, but unacceptable in it’s current form IMHO.

I see two possible solutions to this:

1) A new ‘unexpected:’ construct in switches, which handle cases not known at 
compile time.  This is my favorite option because I think it gives us the most 
freedom to evolve the language in the future.  For example, if we end up adding 
subclassable enums in Swift 12 or something, we will already have a mechanism 
in place to deal with the issues that arise.

2) We version the annotation, and then require any additions to map themselves 
back an existing case for code which doesn’t know about the new case.


I also feel like framing the issue as being about exhaustiveness of enums is 
confusing. It really doesn’t have to be about exhaustiveness at all. I would 
much prefer an annotation like @frozen which can be used for structs as well. 
With @exhaustive you have to start talking about module boundaries, because all 
enums are already exhaustive within the module boundary.  You may find people 
adding @exhaustive for the wrong reasons (i.e. they want their local enum to be 
exhaustive).  Framing the issue as something where we promise not to change the 
API is a much easier mental model to explain to people.

Thanks,
Jon

> On Jan 1, 2018, at 9:48 PM, Chris Lattner via swift-evolution 
>  wrote:
> 
>> On Dec 31, 2017, at 12:14 PM, Matthew Johnson via swift-evolution 
>> > wrote:
>> 
>> I agree that we need a solution to the problem described.  I also agree that 
>> non-exhaustive is most in keeping with the overall design of Swift at module 
>> boundaries.  However, I believe this proposal should be modified before 
>> being accepted
> 
> Thanks for writing this up - you’ve explained a common concern in an 
> interesting way:
> 
>> This is likely to be a relatively rare need mostly encountered by 3rd party 
>> libraries but it will happen.  When it does happen it would be really 
>> unfortunate to be forced to use a `default` clause rather than something 
>> like a `future` clause which will produce an error when compiled against an 
>> SDK where the enum includes cases that are not covered.  I can imagine cases 
>> where this catch-all case would need to do something other than abort the 
>> program so I do not like the `switch!` suggestion that has been discussed.  
>> The programmer should still be responsible for determining the behavior of 
>> unknown cases.
> ..
>> While library authors have a legitimate need to reserve the right to 
>> introduce new cases for some enums this need can be met without taking away 
>> a useful tool for generating static compiler errors when code does not align 
>> with intent (in this case, the intent being to cover all known cases).  
>> Switch statements working with these kinds of enums should be required to 
>> cover unknown cases but should be able to do so while still being statically 
>> checked with regards to known cases.  
> 
> I think that this could be the crux of some major confusion, the root of 
> which is the difference between source packages and binary packages that are 
> updated outside your control (e.g. the OS, or a dynamic library that is 
> updated independently of your app like a 3rd party plugin).  Consider:
> 
> 1) When dealing with independently updated binary packages, your code *has* 
> to implement some behavior for unexpected cases if the enum is 
> non-exhaustive.  It isn’t acceptable to not handle that case, and it isn’t 
> acceptable to abort because then your app will start crashing when a new OS 
> comes out. You have to build some sort of fallback into your app.
> 
> 2) When dealing with a source package that contributes to your app (e.g. 
> through SwiftPM), *YOU* control when you update that package, and therefore 
> it is entirely reasonable to exhaustively handle enums even if that package 
> owner didn’t “intend” for them to be exhaustive.  When *you* chose to update 
> the package, you get the “unhandled case” error, and you have maximal 
> “knowability” about the package’s behavior.
> 
> 
> It seems that your concern stems from the fact that the feature as proposed 
> is aligned around module boundaries, and therefore overly punishes source 
> packages like #2.  I hope you agree that in case #1, that the feature as 
> proposed is the right and only thing we can do: you really do have to handle 
> unknown future cases somehow.
> 
> If I’m getting this right, then maybe there is a variant of the proposal that 
> ties the error/warning behavior to whether or not a module is a source module 
> vs a 

Re: [swift-evolution] Happy new year Swift community.

2018-01-01 Thread Jonathan Hull via swift-evolution
Happy New Year!

> On Dec 31, 2017, at 6:01 PM, Goffredo Marocchi via swift-evolution 
>  wrote:
> 
> Happy new year everybody :)!
> 
> Sent from my iPhone
> 
> On 31 Dec 2017, at 23:43, David Hart via swift-evolution 
> > wrote:
> 
>> Thank you very much and happy new Swift year to everybody.
>> 
>> On 1 Jan 2018, at 00:42, Adrian Zubarev via swift-evolution 
>> > wrote:
>> 
>>> Well some of you guys have to wait a little longer, but I can already wish 
>>> everyone a happy new year from Germany.  
>>> 
>>> -- 
>>> Adrian Zubarev
>>> Sent with Airmail
>>> ___
>>> 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] [Review] SE 0192 - Non-Exhaustive Enums

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

> On Dec 21, 2017, at 11:07 AM, Jordan Rose  wrote:
> 
> Thanks for your comments, Jon. Responses inline.
> 
>> On Dec 20, 2017, at 12:46, Jonathan Hull > > wrote:
>> 
>> 
>>> On Dec 19, 2017, at 2:58 PM, Ted Kremenek via swift-evolution 
>>> > wrote:
>>> When reviewing a proposal, here are some questions to consider:
>>> 
>>> What is your evaluation of the proposal?
>>> 
>> Strong -1 as is.
>> 
>> I think I would support having an explicit ‘futureCase’ which is different 
>> from ‘default’.  Requiring default is asking for bugs.  With a separate 
>> ‘futureCase’, we would still get a compile-time error when all of the 
>> current cases aren’t handled.  Note that ‘ futureCase’ is also different 
>> than ‘default’ in that it wouldn’t have to go at the bottom.  It would only 
>> be triggered when the value isn’t one of the values which was known at 
>> compile time.  We should also bike shed the name of ‘futureCase’ to come up 
>> with something that might allow us to make other types of extendable enums…. 
>>  Maybe something like ‘unknownCase’ or ‘unexpectedCase’.
>> 
>> As for the issue of testing, we could add (later) a universally unexpected 
>> case that non-exhaustive enums can be set to for testing. I am not convinced 
>> that this is actually a big enough issue to warrant that though. Forcing 
>> ‘default’ is a much larger real-world problem, IMO (and this use of 
>> ‘default’ is just as untestable).
> 
> Both of these are discussed in "Alternatives considered", and they have flaws 
> that led me to leave them out of the proposal. Do you have any ideas on how 
> to improve on that?

What are the flaws?  I saw that the ‘Future’ case can’t be tested… but using 
‘default’ is just as untestable in the same way.  Others have given lots of 
examples where it will actually be used.

I think we should reframe it so that instead of talking about exhaustive vs. 
non-exhaustive, all switches need to be exhaustive… but switches over these 
enums need to handle unexpected cases to be considered exhaustive.

I know it is marked as an “alternative”, but it seems clear to me that having 
an ‘unexpected’ case (which only matches cases not known at compile time) is 
the clear answer here.  Something like 75% of  responses have mentioned it.


> 
>> 
>> I also dislike the name @exhaustive because I think it will cause confusion 
>> (i.e. “Of course my Enum is exhaustive”).  I think we should just have 
>> @fixed for both enums and structs. The word fixed has the connotation that 
>> it shouldn’t change.
> 
> I don't think anybody loves "exhaustive", but using the same attribute for 
> enums and structs isn't really appropriate, as discussed in my response to 
> Karl yesterday 
> .
>  I'm not opposed to a better name if we can gravitate towards one, though.

I really like @frozen.  It has a much clearer connotation of what it means, and 
can be used for structs too.

Thanks,
Jon

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


Re: [swift-evolution] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-21 Thread Jonathan Hull via swift-evolution
+1 for @frozen

> On Dec 20, 2017, at 7:16 PM, Brent Royal-Gordon via swift-evolution 
>  wrote:
> 
>> On Dec 19, 2017, at 2:58 PM, Ted Kremenek via swift-evolution 
>>  wrote:
>> 
>>  • What is your evaluation of the proposal?
> 
> I am pleased with the broad strokes of this design. I have quibbles with 
> three areas:
> 
> 1. The `@exhaustive` attribute may be confusing because the term doesn't 
> suggest versioning. My best alternative suggestion is `@frozen`, which 
> matches existing programming terminology: something that has been frozen will 
> not be changed in the future.
> 
> 2. I think we need some kind of `future` keyword in `switch` statements. Even 
> though a nonexhaustive enum may gain additional cases in the future, it's 
> still useful for the compiler to diagnose that you forgot *known* cases.
> 
> You say that "switches over non-exhaustive enums should be uncommon", and 
> this is true for many—perhaps most—non-exhaustive enums, but there is still a 
> large class of non-exhaustive enums which need to be switched over. These are 
> the ones I called "category 2" in my previous email in this thread. 
> `SKPaymentTransactionState` is the example I previously used; others might 
> include `Stream.Status` (if not exhaustive), `CLAuthorizationStatus`, 
> `EKParticipantType`, `PKPaymentMethodType`, and `MKMapType`. Each of these 
> could plausibly have more cases added; each has a good reason why you might 
> switch over cases (such as display in a user interface); and each ought to be 
> promptly updated when a new OS version introduces new cases. Without compiler 
> assistance, those updates won't happen.
> 
> If we plan to add private cases in a future version of Swift, `future` may 
> not be the best keyword. `unknown`, `invalid` (or `case #invalid`), etc. may 
> be better.
> 
> 3. I am very skeptical of treating all enums as exhaustive if imported by 
> `@testable import`. The only reason I can see not to do this is that forcing 
> you to provide `default` might hide tests that need to be updated for new 
> enum cases—but this is the exact problem that `future` is trying to solve. By 
> contrast, treating them as non-exhaustive forces you to actually notice when 
> an enum is published as nonexhaustive and consider whether that's the right 
> approach.
> 
> None of these are showstoppers if left unaddressed, but I think the design 
> would be better if we fixed them.
> 
>>  • Is the problem being addressed significant enough to warrant a change 
>> to Swift?
> 
> Yes. I have no idea how Swift programs currently behave when a future 
> framework version adds a case, but I can't imagine they do anything good.
> 
>>  • Does this proposal fit well with the feel and direction of Swift?
> 
> Yes, with the exception of conflating `default` and `future`, which removes 
> useful correctness checks.
> 
>>  • If you have used other languages or libraries with a similar feature, 
>> how do you feel that this proposal compares to those?
> 
> I've experienced bugs in Objective-C caused by the compiler not knowing an 
> enum might have additional, unknown cases. Debugging them sucked.
> 
>>  • How much effort did you put into your review? A glance, a quick 
>> reading, or an in-depth study?
> 
> I've participated in multiple rounds of discussion on this topic, and read 
> the proposal top-to-bottom for this review.
> 
> -- 
> Brent Royal-Gordon
> Architechies
> 
> ___
> 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] [Review] SE 0192 - Non-Exhaustive Enums

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

> On Dec 19, 2017, at 2:58 PM, Ted Kremenek via swift-evolution 
>  wrote:
> When reviewing a proposal, here are some questions to consider:
> 
> What is your evaluation of the proposal?
> 
Strong -1 as is.

I think I would support having an explicit ‘futureCase’ which is different from 
‘default’.  Requiring default is asking for bugs.  With a separate 
‘futureCase’, we would still get a compile-time error when all of the current 
cases aren’t handled.  Note that ‘ futureCase’ is also different than ‘default’ 
in that it wouldn’t have to go at the bottom.  It would only be triggered when 
the value isn’t one of the values which was known at compile time.  We should 
also bike shed the name of ‘futureCase’ to come up with something that might 
allow us to make other types of extendable enums….  Maybe something like 
‘unknownCase’ or ‘unexpectedCase’.

As for the issue of testing, we could add (later) a universally unexpected case 
that non-exhaustive enums can be set to for testing. I am not convinced that 
this is actually a big enough issue to warrant that though. Forcing ‘default’ 
is a much larger real-world problem, IMO (and this use of ‘default’ is just as 
untestable).

I also dislike the name @exhaustive because I think it will cause confusion 
(i.e. “Of course my Enum is exhaustive”).  I think we should just have @fixed 
for both enums and structs. The word fixed has the connotation that it 
shouldn’t change.

> Is the problem being addressed significant enough to warrant a change to 
> Swift?
> 
Yes, I think the problem is significant, but this is not the correct solution.
> Does this proposal fit well with the feel and direction of Swift?
> 
Not quite.  While I think ABI safety is Swifty, I feel like this design 
actually encourages a lack of safety in other areas.  Much better to explicitly 
deal with the issue of added/future cases in code than to hide it with 
‘default’.

> If you have used other languages or libraries with a similar feature, how do 
> you feel that this proposal compares to those?
> 
I have used Enums in several languages, but Swift is the only one which has 
required exhaustive enums… I have a hard time going back to languages which 
don’t have it now.

> How much effort did you put into your review? A glance, a quick reading, or 
> an in-depth study?
> 
Thoroughly read proposal, casually followed the original discussion.

Thanks,
Jon


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


Re: [swift-evolution] Proposal and Timeline for Discourse Transition

2017-12-13 Thread Jonathan Hull via swift-evolution
I would also like a place in the “Using Swift” for working on libraries or open 
source projects. I think asking for collaborators is fundamentally different 
than asking technical questions.

It would be nice to have support somehow for the idea of working groups for 
evolution


> On Dec 12, 2017, at 3:31 AM, Alejandro Martinez via swift-evolution 
>  wrote:
> 
> This sounds great!
> Specially the new structure, it reminds me of the Rust forums. I just
> have one question, is the Using Swift category expected to be the one
> where the community posts project announcements for new libraries or
> similar stuff? I remember a recent thread where some people wanted to
> include more libs in the standard swift distribution and one of the
> alternatives considered was making it easy for the community to get
> together and share new projects and even join forces. This would seem
> like the perfect place for it, similar to the announcements category
> on Rust forum.
> 
> 
> On Tue, Dec 12, 2017 at 7:42 AM, Ben Rimmington via swift-evolution
>  wrote:
>> [Forum] merging multiple staged accounts
>> 
>> 
>> [Forum] importing names with non-Latin characters
>> 
>> 
>> -- Ben
>> 
>>> On 12 Dec 2017, at 06:41, Ben Rimmington wrote:
>>> 
>>> When claiming a staged account, can the username be changed?
>>> e.g. Having the same "@username" on GitHub and Swift Forums.
>>> 
>>> Will people with multiple accounts be able to merge them?
>>> 
>>> 
>>> Names with non-Latin characters are not imported correctly:
>>> 
>>> e.g. StringTransform("Any-Latin; Latin-ASCII; Any-Title")
>>> 
>>> -- Ben
>> 
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
> 
> 
> -- 
> Alejandro Martinez
> http://alejandromp.com
> ___
> 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] Optional Argument Chaining

2017-12-13 Thread Jonathan Hull via swift-evolution
+1 to this.  I also like Adrian’s notation where the ? is after the name, but 
before the parameter list.

> On Dec 12, 2017, at 7:33 AM, Yuta Koshizawa via swift-evolution 
>  wrote:
> 
> I think evaluating them in the same way as `try` calls is consistent.
> 
> ```
> f(g()?, h()?, i(), j()?)?
> // like
> try f(try g(), try h(), i(), try j())
> ```
> 
> ```
> foo(bar(x()?)) + y()?
> // like
> foo(bar(try x())) + (try y())
> ```
> 
> --
> Yuta
> 
> 
> 2017-12-12 7:42 GMT+09:00 Slava Pestov via swift-evolution
> :
>> 
>> 
>> On Dec 11, 2017, at 2:41 PM, Jared Khan via swift-evolution
>>  wrote:
>> 
>> I missed the previous threads! I’ve found one of the relevant threads here:
>> https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160711/024201.html
>> 
>> Thanks for this important point.
>> 
>> If you were to write this logic out by hand then you would short-circuit it
>> and this is analogous to current chaining behaviour so to me evaluating left
>> to right (as Swift usually does) and stopping at the first failed unwrap
>> would make sense. I wouldn’t necessarily say it’s intuitive but I don’t
>> think it’s really less intuitive than the current chaining behaviour.
>> 
>> 
>> I think it gets confusing when you have multiple levels of nested
>> expressions, eg
>> 
>> foo(bar(x?)) + y?
>> 
>> Slava
>> 
>> 
>> Jared
>> 
>> On 11 Dec 2017, at 19:28, Xiaodi Wu via swift-evolution
>>  wrote:
>> 
>> This topic has been discussed at least two and maybe more times in the
>> past.. It’s hard for me to post links at the moment, but it should be
>> possible to find on Google.
>> 
>> One major challenge to this idea, for which no satisfactory answer has been
>> achieved after all these years, is the following issue:
>> 
>> f(g()?, h()?, i(), j()?)?
>> 
>> If g() evaluates to nil, is h() called or not? How about i(), which is not
>> failable? Since any function or property access can have side effects, in
>> what order are the arguments evaluated, and how does one reason about this
>> code flow?
>> 
>> To my mind, in the absence of an intuitive answer to the above—which does
>> not appear to be possible—this idea is not feasible.
>> On Mon, Dec 11, 2017 at 12:34 Magnus Ahltorp via swift-evolution
>>  wrote:
>>> 
>>> 
 12 Dec. 2017 02:58 Jared Khan  wrote:
 
 2. It felt natural to me. It’s analogous to the existing optional
 chaining scenarios and composes nicely. I think it’s about as 
 understandable
 as existing chaining, a newbie would have to look it up to discover its
 meaning. What are your thoughts on this particular syntax (ignoring 3.
 momentarily)? Hopefully others in this thread can share their views too.
>>> 
>>> Chaining methods is linear, while nesting fills a similar purpose when we
>>> use function calls. This of course affects the way existing Swift code is
>>> written, but that is something we have to live with if we want to use
>>> familiar syntax patterns. However, I think we have to consider this
>>> difference in this case, since the syntax becomes more convoluted. Your
>>> suggestion is definitely not as easy to read as the optional chaining
>>> syntax, and maybe it can't be.
>>> 
 As for how common I’d expect it to be, it’s something I’ve run into
 myself a few times. Again, I hope members of this list can give their view
 on if this would be useful to them.
>>> 
>>> I don't have any real examples, but I certainly think that I have run into
>>> it, so I'm quite open to solving the problem. For me, it is probably only a
>>> matter of finding a syntax that is acceptable.
>>> 
 3. I’m not entirely sure what the grammar situation is yet but afaik ‘?’
 has never been available as a postfix operator. Perhaps I’m missing your
 point, could you demonstrate where it is allowed?
>>> 
>>> I did not expect that you would be able to answer that, it was more a
>>> question directed to people who are more connected to the inner workings of
>>> the parsing of Swift than I am. It is not allowed, but the error message is
>>> not the one I expect, something that gives me a hint that it does have some
>>> meaning early in the parsing.
>>> 
>>> /Magnus
>>> 
>>> ___
>>> 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
>> 

Re: [swift-evolution] Optional Argument Chaining

2017-12-12 Thread Jonathan Hull via swift-evolution
In my opinion, simple left to right evaluation where it short circuits on the 
first failure is the simplest.  But I don’t think it matters that much as long 
as we have a consistent way to define it, and explain it.

It is nice to have forward transfer from other features, but sometimes we just 
need to forge ahead to create something new and then have education on the new 
feature.


> On Dec 11, 2017, at 11:28 AM, Xiaodi Wu via swift-evolution 
>  wrote:
> 
> This topic has been discussed at least two and maybe more times in the past. 
> It’s hard for me to post links at the moment, but it should be possible to 
> find on Google.
> 
> One major challenge to this idea, for which no satisfactory answer has been 
> achieved after all these years, is the following issue:
> 
> f(g()?, h()?, i(), j()?)?
> 
> If g() evaluates to nil, is h() called or not? How about i(), which is not 
> failable? Since any function or property access can have side effects, in 
> what order are the arguments evaluated, and how does one reason about this 
> code flow?
> 
> To my mind, in the absence of an intuitive answer to the above—which does not 
> appear to be possible—this idea is not feasible.
> On Mon, Dec 11, 2017 at 12:34 Magnus Ahltorp via swift-evolution 
> > wrote:
> 
> > 12 Dec. 2017 02:58 Jared Khan > 
> > wrote:
> >
> > 2. It felt natural to me. It’s analogous to the existing optional chaining 
> > scenarios and composes nicely. I think it’s about as understandable as 
> > existing chaining, a newbie would have to look it up to discover its 
> > meaning. What are your thoughts on this particular syntax (ignoring 3. 
> > momentarily)? Hopefully others in this thread can share their views too.
> 
> Chaining methods is linear, while nesting fills a similar purpose when we use 
> function calls. This of course affects the way existing Swift code is 
> written, but that is something we have to live with if we want to use 
> familiar syntax patterns. However, I think we have to consider this 
> difference in this case, since the syntax becomes more convoluted. Your 
> suggestion is definitely not as easy to read as the optional chaining syntax, 
> and maybe it can't be.
> 
> > As for how common I’d expect it to be, it’s something I’ve run into myself 
> > a few times. Again, I hope members of this list can give their view on if 
> > this would be useful to them.
> 
> I don't have any real examples, but I certainly think that I have run into 
> it, so I'm quite open to solving the problem. For me, it is probably only a 
> matter of finding a syntax that is acceptable.
> 
> > 3. I’m not entirely sure what the grammar situation is yet but afaik ‘?’ 
> > has never been available as a postfix operator. Perhaps I’m missing your 
> > point, could you demonstrate where it is allowed?
> 
> I did not expect that you would be able to answer that, it was more a 
> question directed to people who are more connected to the inner workings of 
> the parsing of Swift than I am. It is not allowed, but the error message is 
> not the one I expect, something that gives me a hint that it does have some 
> meaning early in the parsing.
> 
> /Magnus
> 
> ___
> 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] [swift-dev] Re-pitch: Deriving collections of enum cases

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

> On Nov 14, 2017, at 9:06 PM, Brent Royal-Gordon via swift-dev 
>  wrote:
> 
>> On Nov 14, 2017, at 5:21 PM, Xiaodi Wu > > wrote:
>> 
>> 1. It must be possible to easily access the count of values, and to access 
>> any particular value using contiguous `Int` indices. This could be achieved 
>> either by directly accessing elements in the list of values through an Int 
>> subscript, or by constructing an Array from the list of values.
>> 
>> 2. It must be possible to control the order of values in the list of values, 
>> either by using source order or through some other simple, straightforward 
>> mechanism.
>>  
>> OK, first of all, nowhere in the proposal text are these requirements stated 
>> as part of the use case. You're free to put forward new use cases, but here 
>> I am trying to design the most elegant way to fulfill a stated need and 
>> you're telling me that it's something other than what's written.
> 
> Honestly, re-reading the proposal, it never cites a fully-formed use case. 
> Instead, it cites several blog posts, Stack Overflow questions, and small 
> code samples without digging in to the underlying reasons why developers are 
> doing what they're doing. Most of the people discussing it so far seem to 
> have had a tacit understanding that we wanted roughly Array-like access, but 
> we haven't explicitly dug into which properties of an Array are important.
> 
> (If anyone involved feels like they had a different understanding of the use 
> case, please speak up.)
> 
> I think this is a place where the proposal can be improved, and I'm willing 
> to do some writing to improve it.


This is a feature I have been requesting since Swift 1.  If the resulting 
ordering is not SOURCE ordering, this feature loses most of it’s usefulness for 
me. I would say around 80% of my uses for this require a predictable ordering 
(and I don’t consider something based on compiler internals predictable) which 
I can control.  As Brent said, most of those cases involve something that shows 
to the user in some way.  The weekday example was a good one (I actually have 
that in my code).  

The most painful case of this being missing was where I needed an enum of all 
country codes (it is a beast to maintain).  In that case, I am displaying them 
to the user in a tableView (along with icons named by the country codes), but I 
am also filtering them based on the user’s input in a search field.  To do 
both, you need to be able to iterate/filter an array of cases. Awful to build. 
Just awful.

Also, I would greatly prefer an allValues/allCases method to having the type be 
a collection. It just reads clearer in code what is going on.  I think what I 
basically want to see is:

protocol ValueEnumerable {
var allValues:Collection
}

…where both the conformance and implementation are automatically inferred for 
enums when possible.

I would probably also end up using this protocol on Structs that I use as 
extensible enums.  That is, I have a private/internal initializer and use 
static vars in place of the cases.  This isn’t perfect, since part of the 
reason I use these structs is that they can be built in a distributed way… but 
I could find a way to build that array in a mostly distributed way as well (and 
if we ever get the Multi-function capability I have suggested elsewhere, then 
it could be truly distributed).

Semantically, the protocol should infer not only a finite number of cases, but 
a number that can be iterated over in a reasonable period of time.  I would be 
fine with Bool conforming, but not with Int.  With those semantics, I could 
easily see a follow-on proposal which says that associated cases where all of 
the values are ValueEnumerable are ValueEnumerable themselves.  This would be 
super useful for cascading enums.  I have a game that I am working on in my 
spare time right now, where effects of actions are represented as enums, with a 
single enum for all effects that references more specific enums for each type 
of thing that can be affected.


One other common need which I feel I should bring up even though it is a bit 
tangential, is that when I have enums with associated values, 90% of the time, 
I end up wanting a way to refer to the base of that without the value.  For 
example, if the player has a case called ‘damage’ which has an associated Int, 
I end up wanting to ask (and sometimes store) if the case is a ‘damage’ case.  
Often, I am trying to match against patterns: Were there two damages followed 
by a block?  What I end up doing is creating a second enum with the same cases 
(sans values) and then creating a mapping between the two. Busywork in the same 
way writing these allValues arrays are busywork.  If we end up creating a way 
to reference just the base, maybe the allValues array should just contain those 
bases for non-enumerable associated values. Food for 

Re: [swift-evolution] Proposal: Introduce User-defined "Dynamic Member Lookup" Types

2017-12-05 Thread Jonathan Hull via swift-evolution
Ok, I have changed my mind about the need for a marker, and will accept the 
proposal as-is.  I realized that these dynamic member lookup types can just be 
made inner types, and so I can easily create the .dynamic behavior in my own 
code if I want under the current proposal.  I also realized that requiring a 
marker would screw up the proxy use-case of this.

I do still have a couple of questions I am confused on:

1) How do operators work with this?  I saw you give an example of a+b for 
python types, but I don’t see where either proposal bridges operators. (I could 
easily have missed it though)

2) What if I need two separate python libraries?  The code says ‘let np = 
Python.import(“numpy”)’.  Are we supposed to make a separate variable for each 
import?

3) How will inter-op between Swift types and Python types work?  It looks like 
you are just passing strings and integer constants to python functions. Do they 
get converted automatically, or do we have to explicitly convert them?  I am 
guessing this is using expressibleBy___ to work?

Also, I would still really like to see a different coloring/styling for methods 
which fall down to this protocol.

Thanks,
Jon



> On Dec 4, 2017, at 7:30 PM, Chris Lattner via swift-evolution 
>  wrote:
> 
>> On Dec 4, 2017, at 5:22 PM, Joe DeCapo via swift-evolution 
>>  wrote:
>>> The first one, has no static type info, no compile time checking, it's not 
>>> self documenting, no type inference so people will be forced to use a 
>>> dynamic reference at the call site to store the result, leading to more 
>>> type loss, and all this spirals down.
>>> I'm already starting to fear dynamic.
>>> Edit: The danger has passed (Phew!) ... and dynamic wasn't been abused 
>>> after all, no need to down vote me after 3 years :)
>> 
>> From what I can gather, `dynamic` is used when declaring types, but there's 
>> no indication at call sites that what is being invoked is dynamic. And it 
>> even allows for casting basically anything to the `dynamic` type.
>> 
>> https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/dynamic
>> 
>> So here we have a language community that was (is?) very vocal about caution 
>> when it comes to type inference with `var`, but seems to have accepted the 
>> validity of `dynamic`. This seems to show that at least one community has 
>> absorbed this sort of change (arguably a more "dangerous" version than what 
>> is being proposed here) with no real issues.
> 
> Right.  dynamic in C# is far broader (and more “dangerous”) than what I’m 
> proposing.  That said, because there have been absolutely zero specific 
> examples of the sorts of harm DynamicMemberLookup could cause, it is 
> difficult to speculate about exactly which boogieman people are afraid of.
> 
>> So I have a few questions:
>> 
>> - Would it be enough to require annotation of the dynamic nature of a type 
>> at the declaration sites, if that still means the call sites aren't 
>> explicitly annotated? 
> 
> It is impossible to solve a problem if it cannot be explained in enough 
> detail to provide examples.  Personally, I don’t see the problem at all.
> 
>> - Why do some think the Swift community would be more at risk of abuse of 
>> this feature than the C# community seems to have been? 
> 
> 
> People are making bizarre claims about what the spirit of Swift is, informing 
> me of things which are obviously not true, and ignoring the evidence I 
> present to them.  This is doubly humorous given that I have a fairly good 
> sense for the design balance and tradeoffs of existing features in Swift 
> today, along with detailed rationale for why they were added, when, and all 
> of the discussion that backed them.  I chalk this up to the fear of the 
> unknown or perhaps a mistrust for the peers these people work with.
> 
> My goal is to make the design and proposal writeup as good as possible, and 
> the fear mongering about abuse has led me to add several options for further 
> narrowing the potential for abuse, including to the point of requiring every 
> new adoptee to go through the Swift evolution process for review.  During the 
> review period for DynamicMemberLookup, people who carry these concerns are 
> welcome to +1 one or more of those.
> 
> I personally am far more interested in getting to the bottom of Doug’s 
> concerns - it isn’t clear to me what exactly his preferred direction actually 
> is, but that discussion is based on engineering tradeoffs and may well lead 
> to a change to the proposal or a complete change in direction.
> 
> -Chris
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

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


Re: [swift-evolution] Proposal: Introduce User-defined "Dynamic Member Lookup" Types

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

> On Dec 3, 2017, at 9:39 AM, Chris Lattner  wrote:
> 
> On Dec 3, 2017, at 5:45 AM, Jonathan Hull  > wrote:
>> Hi Chris,
>> 
>> I am definitely in favor of providing dynamic features in Swift, and of 
>> being able to interoperate easily with dynamic languages. I really like the 
>> idea overall.
> 
> Great!
> 
>> 
>> I was about to write up a different idea I had for partially mitigating some 
>> of the issues around being able to mistype method names, etc…, but then I 
>> remembered a usability principle that I first heard from members of the Lisa 
>> team (discovered the hard way): Things which behave the same should look the 
>> same, and things which behave differently need to look different.
> 
> That’s a good principle.  However, a dynamic member lookup is just a member 
> lookup.  By that principle, it should look like a member lookup :-)

The behavior is different though (the invisible guard rails which we normally 
rely on to prevent mistakes are missing), so it should look similar without 
being identical.

If Swift were entirely dynamic, there wouldn’t be an issue here, because 
developers would have strategies for dealing with it. It is the rarity of use 
that causes the issue here.  Swift developers have built up trust in the system 
to catch their typing mistakes, so if we make it so that the system can 
silently fail, there will be an increased error rate (above what you would have 
in a purely dynamic system).

Let me give a non-computer analogy. There are lots of arguments about whether 
the toilet seat should always be put down for the next user or just be left in 
it’s current position.  Some households have them randomly up or down based on 
who used them last. This equates to the dynamic case because no trust can be 
built that the seat will be down, so everyone learns to check before sitting. 
Let’s say we add a foot pedal though, which raises the seat when you step on 
it, and lowers it when it is not pressed (like a garbage can lid).  Now 
everyone can reason about the state of the system and can trust that it will be 
down unless they step on the pedal.  As a result, over time, people will be 
able to just sit without checking.  This is great, but if we re-introduce a 
little bit of dynamism (let’s say someone can lift the seat without using the 
pedal and it will stay up)… now the people who have built trust in the system, 
and just sit, will fall in.

The end result is that either some trust is lost in the system as a whole 
(people use the dynamic way of thinking when they don’t need to) or they 
continue to have errors when dealing with the rare dynamic cases.

I also like Paul’s suggestion of different syntax coloring for the dynamic 
calls.  In the toilet seat analogy, it is like one of those little lights you 
can buy that turns green or red depending on whether the seat is up or down.


> Further, I incorporated some of the conversation with Matthew into the 
> proposal, showing how adding even a single sigil to dynamic member lookup to 
> distinguish it is problematic:
> https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438#increasing-visibility-of-dynamic-member-lookups
>  
> 
> 
> Further, adding something like .dynamic would completely undermind the 
> proposal.  You can already write:
> 
>   x.get(“foo”).get(“bar”)
> 
> having to write:
> 
>   x.dynamic.foo.dynamic.bar
> 
> has no point.

Oh no, I meant a single ‘dynamic’ would enable dynamic lookup for the entire 
chain, so it would be:

x.dynamic.foo.bar

This is different than requiring a sigil for each lookup.


>> What this means is that it is easy to wrap commonly used calls in a normal 
>> swift method:
>> 
>>  func addTrick(_ name:String) {
>>  self.dynamic.add_trick(name)
>>  }
> 
> This would require wrapping all calls for them to be usable.

I don’t think that chaining with ‘dynamic' is too large of a burden (when it 
works for the entire chain), so that would be the fallback for calls that 
haven’t been wrapped. Even if calls are never wrapped, I think this is workable.

My expectation though is that frequently used calls would end up getting 
wrapped eventually, and the wrappers would covert to/from Swift types.  
Basically, I want a system which encourages people to thoughtfully Swift-ify™ 
the interface for working with python code incrementally over time. Python 
coders may have no incentive to do this, but Swift users of that code sure do.

I guess what I am arguing is that we should prioritize/optimize the ease of 
creating that translation layer at the cost of making pure/direct calls into 
Python require an extra word of typing.  Two birds, one stone.

Thanks,
Jon


___
swift-evolution mailing list
swift-evolution@swift.org

Re: [swift-evolution] Proposal: Introduce User-defined "Dynamic Member Lookup" Types

2017-12-03 Thread Jonathan Hull via swift-evolution
Hi Chris,

I am definitely in favor of providing dynamic features in Swift, and of being 
able to interoperate easily with dynamic languages. I really like the idea 
overall.

I was about to write up a different idea I had for partially mitigating some of 
the issues around being able to mistype method names, etc…, but then I 
remembered a usability principle that I first heard from members of the Lisa 
team (discovered the hard way): Things which behave the same should look the 
same, and things which behave differently need to look different.

I like that the change in behavior is really limited in scope by this proposal, 
but there still isn’t really any indication other than the type (which might be 
inferred) that the normal checking behavior is offline.  When in a fully 
dynamic environment, this isn’t really a big problem because you use different 
debugging strategies,  but I worry that the free mixture of static and dynamic 
without any indicators showing the difference will lead to much more frequent 
errors.

What do you think about having a special method ‘dynamic' defined in this 
protocol, such that the compiler magic lookup behavior is only available when 
chained after that method?  Thus:

dog.add_trick(“sit”)

would have to be:

dog.dynamic.add_trick(“sit”)


Now, I know that sounds like a pain in the butt, but it also buys you an extra 
ability (in addition to the extra cue that we have to watch out for dynamic 
issues).  Because the dynamic lookup only happens for calls chained after 
dynamic, we now have normal swift lookup for all of the other 
methods/properties defined on the type (with autocomplete support, etc…).

What this means is that it is easy to wrap commonly used calls in a normal 
swift method:

func addTrick(_ name:String) {
self.dynamic.add_trick(name)
}

Now the user can say the following with full autocomplete support, type 
checking, etc…

addTrick(“sit”)

…and if they misspell it, they will get an error from the compiler.  Error 
handling could also optionally be added to a wrapper.  Most importantly, 
conversion to/from swift return types and parameters can easily be built into 
the wrappers.

The end result is a system where python code can be up and running in Swift 
very quickly (by using chaining with .dynamic), and then made more native Swift 
friendly incrementally over time (by adding wrappers/extensions for 
common/important calls).  The only extra cost is having to type an extra word 
for dynamic calls without wrappers.

Thoughts?

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-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 Jonathan Hull via swift-evolution

> On Nov 30, 2017, at 4:11 PM, Xiaodi Wu <xiaodi...@gmail.com> wrote:
> 
> On Thu, Nov 30, 2017 at 5:29 PM, Jonathan Hull <jh...@gbis.com 
> <mailto:jh...@gbis.com>> wrote:
> 
>> On Nov 30, 2017, at 2:30 PM, Xiaodi Wu <xiaodi...@gmail.com 
>> <mailto:xiaodi...@gmail.com>> wrote:
>> 
>> On Thu, Nov 30, 2017 at 3:58 PM, Dave DeLong via swift-evolution 
>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>> 
>> 
>>> On Nov 30, 2017, at 2:48 PM, Jonathan Hull via swift-evolution 
>>> <swift-evolution@swift.org <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* exp

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 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 Jonathan Hull via swift-evolution

> On Nov 30, 2017, at 3:19 PM, Dave DeLong <sw...@davedelong.com> wrote:
> 
> 
> 
>> On Nov 30, 2017, at 4:08 PM, Jonathan Hull <jh...@gbis.com 
>> <mailto:jh...@gbis.com>> wrote:
>> 
>> 
>>> On Nov 30, 2017, at 1:58 PM, Dave DeLong <sw...@davedelong.com 
>>> <mailto:sw...@davedelong.com>> wrote:
>>> 
>>> 
>>> 
>>>> On Nov 30, 2017, at 2:48 PM, Jonathan Hull via swift-evolution 
>>>> <swift-evolution@swift.org <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 Jonathan Hull via swift-evolution

> On Nov 30, 2017, at 2:30 PM, Xiaodi Wu <xiaodi...@gmail.com> wrote:
> 
> On Thu, Nov 30, 2017 at 3:58 PM, Dave DeLong via swift-evolution 
> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
> 
> 
>> On Nov 30, 2017, at 2:48 PM, Jonathan Hull via swift-evolution 
>> <swift-evolution@swift.org <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 impleme

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

2017-11-30 Thread Jonathan Hull via swift-evolution
Agreed.  Type.random should call Type.random(using:) with the (publicly 
available) default.  In fact, if we wanted to make it Type.random() it should 
basically be the default value of ‘using:’

Thanks,
Jon


> On Nov 30, 2017, at 3:03 PM, TellowKrinkle <tellowkrin...@gmail.com> wrote:
> 
> Whether or not it’s possible to hide, I think that the default RNG should be 
> exposed publicly, so that functions like `CustomType.random(using:)` will 
> take a RandomSource property instead of just using the system RNG, allowing 
> someone to specify a different RNG (maybe a seedable PRNG for example) to 
> suit their needs.
> 
>> 2017/11/30 16:30、Xiaodi Wu <xiaodi...@gmail.com 
>> <mailto:xiaodi...@gmail.com>>のメール:
>> 
>> On Thu, Nov 30, 2017 at 3:58 PM, Dave DeLong via swift-evolution 
>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>> 
>> 
>>> On Nov 30, 2017, at 2:48 PM, Jonathan Hull via swift-evolution 
>>> <swift-evolution@swift.org <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-

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

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

> On Nov 30, 2017, at 1:58 PM, Dave DeLong <sw...@davedelong.com> wrote:
> 
> 
> 
>> On Nov 30, 2017, at 2:48 PM, Jonathan Hull via swift-evolution 
>> <swift-evolution@swift.org <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).

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?


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

I don’t have a strong opinion on this. I would be ok with methods.

> 
>> 
>> 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 
>>> <swift-evolution@swift.org <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` h

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 
> > 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 > >のメール:
>> 
>> 
>> - 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 

Re: [swift-evolution] [Pitch #2] Introduce User-defined "Dynamic Member Lookup" Types

2017-11-29 Thread Jonathan Hull via swift-evolution
I noticed all of the examples return the same type as they are defined on (JSON 
has a subscript that returns JSON).  Is there an example of where this is not 
the case?


> On Nov 25, 2017, at 3:16 PM, Chris Lattner via swift-evolution 
>  wrote:
> 
> On Nov 20, 2017, at 10:36 PM, Chris Lattner  > wrote:
>> Hi all,
>> 
>> I’ve significantly revised the ‘dynamic member lookup’ pitch, here’s the 
>> second edition:
>> https://gist.github.com/lattner/b016e1cf86c43732c8d82f90e5ae5438 
>> 
>> 
>> I’ve incorporated some minor changes to it:
>> - I’ve made it possible to provide read-only dynamic members.
>> - I’ve added an example JSON use-case which uses read-only dynamic members.
>> - Minor wording changes.
> 
> Just to talk to myself a bit here, but I’ve come to realize that the right 
> design really is to have a simple empty marker protocol like this:
> 
> /// Types type conform to this protocol have the behavior that member lookup -
> /// accessing `someval.member` will always succeed.  Failures to find normally
> /// declared members of `member` will be turned into subscript references 
> using
> /// the `someval[dynamicMember: member]` member.
> ///
> public protocol DynamicMemberLookupProtocol {
>   // Implementations of this protocol must have a subscript(dynamicMember:)
>   // implementation where the keyword type is some type that is
>   // ExpressibleByStringLiteral.  It can be get-only or get/set which defines
>   // the mutability of the resultant dynamic properties.
>   
>   // subscript
>   //  (dynamicMember name: KeywordType) -> LookupValue { get }
> }
> 
> 
> A design like this can almost work:
> 
> public protocol DynamicMemberLookupProtocol {
>   associatedtype DynamicMemberLookupKeyword : ExpressibleByStringLiteral
>   associatedtype DynamicMemberLookupValue
>   
>   subscript(dynamicMember name: DynamicMemberLookupKeyword)
> -> DynamicMemberLookupValue { get }
> }
> 
> The problem is that now everything that conforms to 
> DynamicMemberLookupProtocol is a PAT, so it doesn’t work with existentials.  
> We could almost make due with a generic subscript:
> 
> public protocol DynamicMemberLookupProtocol {
>   subscript
> (dynamicMember name: KeywordType) -> LookupValue { get }
> }
> 
> but it turns out that while you can declare that, nothing can actually 
> conform to it with concrete types (I filed SR-6473, but it isn’t clear that 
> it ever can work given how our generics system works).
> 
> Defining this as an empty marker protocol has several advantages:
>  - Only one protocol is required
>  - Suddenly you can define mutating getters and nonmutating setters
>  - Existentials work as well as concrete types.
> 
> -Chris
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

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


Re: [swift-evolution] Synthesizing Equatable, Hashable, and Comparable for tuple types

2017-11-28 Thread Jonathan Hull via swift-evolution
+1.  It seems like a practical first step.

> On Nov 28, 2017, at 10:59 AM, Joe Groff via swift-evolution 
>  wrote:
> 
> 
> 
>> On Nov 28, 2017, at 10:52 AM, Vladimir.S  wrote:
>> 
>> On 27.11.2017 20:28, Joe Groff via swift-evolution wrote:
 On Nov 20, 2017, at 5:43 PM, Chris Lattner via swift-evolution 
 > wrote:
 
 
> On Nov 20, 2017, at 5:39 PM, Kelvin Ma via swift-evolution 
> > wrote:
> 
> when SE-185 
> 
>  went through swift evolution, it was agreed that the next logical step 
>  is 
> synthesizing these conformances for tuple types, though it was left out 
> of the original proposal to avoid mission creep. I think now is the time 
> to start thinking about this. i’m also tacking on Comparable to the other 
> two protocols because there is precedent in the language from SE-15 
> 
>  that tuple comparison is something that makes sense to write.
> 
> EHC conformance is even more important for tuples than it is for structs 
> because tuples effectively have no workaround whereas in structs, you 
> could just manually implement the conformance. 
 
 In my opinion, you’re approaching this from the wrong direction.  The 
 fundamental problem here is that tuples can’t conform to a protocol.  If 
 they could, synthesizing these conformances would be straight-forward.
>>> It would be a tractable intermediate problem to introduce built-in 
>>> conformances for tuples (and perhaps metatypes) to 
>>> Equatable/Hashable/Comparable without breaching the more general topic of 
>>> allowing these types to have general protocol conformances. I think that 
>>> would cover the highest-value use cases.
>> 
>> So, shouldn't we do this first step ASAP and then design a good common 
>> solution to allow tuples/metatypes/funcs to confirm to custom protocols in 
>> some next version of Swift?
>> I really believe this is the good practical decision and will be supported 
>> by community if such proposal will be on the table.
>> Is there any drawback in such step?
> 
> The expected behavior of tuple Equatable/Hashable/Comparable seems obvious to 
> me (though I could well be missing something), and any behavior we hardcode 
> should be naturally replaceable by a generalized conformance mechanism, so 
> it's primarily a "small matter of implementation". There would be some 
> implementation cost to managing the special case in the compiler and runtime; 
> the tradeoff seems worth it to me in this case, but others might reasonably 
> disagree. Not speaking for the entire core team, I would personally support 
> considering a proposal and implementation for builtin tuple 
> Equatable/Hashable/Comparable conformance.
> 
> -Joe
> ___
> 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] [Pitch] Nested types in protocols (and nesting protocols in types)

2017-11-26 Thread Jonathan Hull via swift-evolution
I would use this pretty much constantly!  I thought it was going to be in Swift 
4, and have really been missing it…


> On Nov 26, 2017, at 8:51 AM, Adrian Zubarev via swift-evolution 
>  wrote:
> 
> 
> What happened to this? Should we revive this talk? I’d love to finally be 
> able to nest protocols in Swift 5 and clean up my code.
> 
> Am 18. Januar 2017 um 09:48:20, Slava Pestov via swift-evolution 
> (swift-evolution@swift.org ) schrieb:
> 
>> I left some review comments here:
>> 
>> https://github.com/apple/swift-evolution/commit/ff654e4 
>> 
>> 
>> Slava
>> 
>>> On Jan 18, 2017, at 12:17 AM, Karl Wagner >> > wrote:
>>> 
>>> 
 On 18 Jan 2017, at 01:07, Douglas Gregor > wrote:
 
 
> On Nov 5, 2016, at 2:44 AM, Karl via swift-evolution 
> > wrote:
> 
>> 
>> On 2 Nov 2016, at 20:54, Slava Pestov > > wrote:
>> 
>>> 
>>> On Nov 2, 2016, at 8:32 AM, Paul Cantrell >> > wrote:
>>> 
>>> 
 On Oct 24, 2016, at 4:43 PM, Slava Pestov > wrote:
 
 
> On Oct 24, 2016, at 8:12 AM, Paul Cantrell  > wrote:
> 
> 
>> On Oct 24, 2016, at 5:09 AM, Slava Pestov via swift-evolution 
>> > wrote:
>> 
>> However protocols nested inside types and types nested inside 
>> protocols is still not supported, because protocols introduce a 
>> separate series of issues involving associated types and the ’Self’ 
>> type.
>> 
>> The hard part of getting nested generics right is what to do if a 
>> nested type ‘captures’ generic parameters of the outer type. For 
>> non-protocol types, the behavior here is pretty straightforward.
>> 
>> If we allow protocols to be nested inside other types, we have to 
>> decide what to do if the protocol ‘closes over’ generic parameters 
>> of the outer type. For example,
>> 
>> struct A {
>> protocol P {
>> func requirement() -> T
>> }
>> }
>> 
>> Presumably A.P and A.P are distinct types, and A.P has 
>> a hidden associated type corresponding to the type parameter ’T’?
>> 
>> The other case is problematic too — the nested type might refer to 
>> an associated type of the outer protocol:
>> 
>> protocol P {
>> associatedtype A
>> 
>> struct T {
>> var value: A
>> }
>> }
>> 
>> Now writing P.T does not make sense, for the same reason that we 
>> cannot form an existential of type P.A. We could prohibit references 
>> to outer associated types of this form, or we could figure out some 
>> way to give it a meaning. If C is a concrete type conforming to P, 
>> then certainly C.T makes sense, for instance. Internally, the nested 
>> type A.T could have a hidden ‘Self’ generic type parameter, so that 
>> writing C.T is really the same as P.T.
>> 
>> Protocols nested inside protocols also have the same issue.
> 
> FWIW, in almost all the situations where I’ve wanted to nest types 
> inside protocols and generic types, it’s only as a namespacing 
> convenience. Most often, it’s an enum type that’s used only by a 
> single method, and having it at the top of the module namespace adds 
> clutter.
> 
> Here’s a real life example pared down. I wish I could do this:
> 
> public struct ResponseContentTransformer OutputContentType>: ResponseTransformer {
> 
>   public init(onInputTypeMismatch mismatchAction: 
> InputTypeMismatchAction = .error) {
> ...
>   }
> 
>   public enum InputTypeMismatchAction {  // Does not depend on 
> generic types above
> case error
> case skip
> case skipIfOutputTypeMatches
>   }
> 
> }
> 
> InputTypeMismatchAction is tightly associated with 
> ResponseContentTransformer, and is confusing as a top-level type.
> 
> What do you think about providing a “no captures” modifier for nested 
> types — like static inner classes in Java? Then Swift could provide 
> the namespace nesting I wish for this without 

Re: [swift-evolution] [Pre-pitch] Conditional default arguments

2017-11-26 Thread Jonathan Hull via swift-evolution
I have wanted something similar to this for a while, and haven’t suggested it 
for a while for the same reason… I can’t really think of a good syntax.

My best idea so far is to put it after the function declaration but before the 
open brace:

func myCrazyFunction(myParam: T)->Int
@default myParam = 0 where T == Int.Self
@default myParam = “” where T == String.Self
{
//Function body goes here
}

When multiple options are available, it would match the most specific one that 
qualifies.  The idea I had would also allow it to have expressions on the rhs, 
and would potentially allow other input types outside of T (as long as the rhs 
returns T):

func evenCrazier(myParam: String)->Int
@default myParam = “\($0)” where myParam : CustomStringConvertible
{
//Function body goes here
}

There are some obvious issues with the syntax here (e.g. I am using $0), but I 
think the general idea is a really useful one.  That is, I am able to provide a 
conversion formula that lets someone pass anything which is 
customStringConvertible to this String parameter and have it pass the 
appropriate String to my actual function. I would use this constantly, and it 
would prevent the combinatorial explosion of overloads I have now…

This also gets rid of the need for the 
often-requested-but-never-going-to-happen union types:

enum MyEnum {
case int (Int)
case str (String)
}

func noNeedForUnion(_ intOrStr: MyEnum)
@default intOrStr = .int($0) where intOrStr == Int.Self
@default intOrStr = .str($0) where intOrStr == String.Self
{
//Function body here
}

noNeedForUnion(3) //This passes .int(3)
noNeedForUnion(“Hey”) //this passes .str(“Hey”)

I could see this making a bunch of frameworks nicer to use… (or at least nicer 
to write)

Thanks,
Jon


> On Nov 24, 2017, at 3:11 PM, Matthew Johnson via swift-evolution 
>  wrote:
> 
> As mentioned in my prior message, I currently have a PR open to update the 
> generics manifesto (https://github.com/apple/swift/pull/13012 
> ).  I removed one topic from that 
> update at Doug Gregor’s request that it be discussed on the list first.  
> 
> The idea is to add the ability to make default arguments conditional (i.e. 
> depend on generic constraints).  It is currently possible to emulate 
> conditional default arguments using an overload set.  This is verbose, 
> especially when several arguments are involved.  Here is an example use case 
> using the overload method to emulate this feature:
> 
> ```swift
> protocol Resource {
>   associatedtype Configuration
>   associatedtype Action
> }
> struct ResourceDescription {
>   func makeResource(with configuration: R.Configuration, actionHandler: 
> @escaping (R.Action) -> Void) -> R {
> // create a resource using the provided configuration
> // connect the action handler
> // return the resource
>   }
> }
> 
> extension ResourceDescription where R.Configuration == Void {
>   func makeResource(actionHandler: @escaping (R.Action) -> Void) -> R {
> return makeResource(with: (), actionHandler: actionHandler)
>   }
> }
> 
> extension ResourceDescription where R.Action == Never {
>   func makeResource(with configuration: R.Configuration) -> R {
> return makeResource(with: configuration, actionHandler: { _ in })
>   }
> }
> 
> extension ResourceDescription where R.Configuration == Void, R.Action == 
> Never {
>   func makeResource() -> R {
> return makeResource(with: (), actionHandler: { _ in })
>   }
> }
> 
> ```
> 
> Adding language support for defining these more directly would eliminate a 
> lot of boilerplate and reduce the need for overloads.  Doug mentioned that it 
> may also help simplify associated type inference 
> (https://github.com/apple/swift/pull/13012#discussion_r152124535 
> ).
> 
> The reason that I call this a pre-pitch and one reason Doug requested it be 
> discussed on list is that I haven’t thought of a good way to express this 
> syntactically.  I am interested in hearing general feedback on the idea.  I 
> am also looking for syntax suggestions.
> 
> Matthew
> ___
> 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] [swift-evolution-announce] [Accepted and Focused Re-review] SE-0187: Introduce Sequence.filterMap(_:)

2017-11-21 Thread Jonathan Hull via swift-evolution
What about mapOrNil?


> On Nov 21, 2017, at 3:00 PM, Wallacy via swift-evolution 
>  wrote:
> 
> Let’s think I little. If the ideia is choose the best name to explain the 
> function:
> 
> If the function drop the nil values and after that does a map operation. 
> Names like dropNilAndMap make sense, right?
> 
> But we are talking about functions that mimics the berraviour of Functional 
> programming languages, doesn’t apear the be “functional” drop nils and make a 
> map in the same operation instead in two steps: dropNils().map{**}
> 
> I think we only need to make a function (or a property) to easily drop 
> (remove or whatever name) and then feal free to call a map or other function 
> on it. (Or call a map and drop the nils after, how knows)
> 
> The role problem is the operation by itself, is confusing because is too 
> specific and the main use for this is the identity operation for just remove 
> the optional level.
> 
> Array.ToNonOptional()
> Array.DropNil()
> Array.WithNonOptional()
> Etc...
> 
> If we only focus in this functionality, the ‘map’ part is already solved.
> 
> 
> Em ter, 21 de nov de 2017 às 08:47, Benjamin G via swift-evolution 
> > escreveu:
> I have a question regarding the general term "compact" vs something more 
> specific like "remove nil" : 
> Could we imagine other usages on different types for "compact" ?
> 
> map / flatmap has the whole category theory behind it, making it meaningful 
> for many different types. "Filter" is also generic, because the operation of 
> filtering has a wide range of application. 
> 
> "Compact", like Tino suggested, would have the general meaning of "reducing 
> the size by removing similar elements". Removing nils doesn't seem to be a 
> special case of this general definition. 
> 
> If we give "compact" the strict definition of "removing nil", then i don't 
> understand the need for a general term, instead of something like "dropNils" 
> (not much longer to write).
> 
> 
> On Tue, Nov 21, 2017 at 10:47 AM, Tino Heth via swift-evolution 
> > wrote:
> My favorite would be a variation of Scalas choice (collect / collectResults).
> The word compact (or similar choices like condense, squeeze, pack, compress…) 
> always remind me on compression — my first association of „compact“ would be 
> a transform that turns [1, 2, 2, 3] into [1, 2, 3] (like the shell tool uniq).
> But there’s a long list of verbs with similar meaning, so if there’s a 
> consensus for compact (or compacted…), I join that camp.
> ___
> 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] [Review] SE-0190: Target environment platform condition

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

> On Nov 16, 2017, at 2:23 PM, Ted Kremenek via swift-evolution 
>  wrote:
> 
> When reviewing a proposal, here are some questions to consider:
> 
> What is your evaluation of the proposal?
> 
I think the functionality is good, but I would like to see some thought on what 
future values could be to see if this is the best name/structure.

If it is just going to be the concept of a simulator, then something like 
isSimulated() might be better.  In the current form, I think we should have 
both ‘Simulator’ and ‘Device’ as options.

I would also like to see something shorter than targetEnvironment(), but it is 
somewhat infrequently used, so it isn’t that big a deal.  It is just compared 
to os() and arch(), this is kind of a beast.  It is a power user thing, so 
maybe something like ‘env()’ would work?  I normally try to avoid 
abbreviations, but we have arch() as precedent.  The word ‘Simulator’ should be 
what stands out...

Would Testing be a possible future environment?

> Is the problem being addressed significant enough to warrant a change to 
> Swift?
> 
Yes, Definitely!

> Does this proposal fit well with the feel and direction of Swift?
> 
Yes.
> If you have used other languages or libraries with a similar feature, how do 
> you feel that this proposal compares to those?
> 
I guess Objective C had something like this as well, which was more powerful, 
but also more messy.
> How much effort did you put into your review? A glance, a quick reading, or 
> an in-depth study?
> 
Quick Read

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


Re: [swift-evolution] [swift-evolution-announce] [Accepted and Focused Re-review] SE-0187: Introduce Sequence.filterMap(_:)

2017-11-20 Thread Jonathan Hull via swift-evolution
I agree that filterMap is just as confusing and awkward as flatMap, if not 
more.  Filter works on Bools, not nils.  It is just asking for 
trouble/confusion, and I would hate to rename this again next year.  If the 
word ‘filter’ must be used, then I recommend using ‘filteringMap()’ to lessen 
confusion with the filter method.

I like the idea of introducing compacted() and compactedMap(), though it only 
works if we introduce compacted() at the same time (which I am ok with).  I 
keep expecting it to be a compact map in the topological sense, but I doubt 
that is a problem most will have.


The only real way to get forward transfer here (besides leaving it alone) is to 
do one of the following:

• Use a name used by another language (that doesn’t conflict with Swift)

• Introduce a concept of removing nils in Swift and call it the same 
thing (e.g. compacted)

• Have an awkward, long, and overly specific name like mapAndRemoveNils

I think it might make sense to just drop the quest for forward transfer, and 
instead look for a short, readable, and memorable name that makes sense in 
hindsight once you have seen it (e.g. dropMap?).  That, or introduce a word 
that means to remove nils.

Thanks,
Jon


> On Nov 20, 2017, at 9:22 AM, BJ Homer via swift-evolution 
>  wrote:
> 
> 
> 
>> On Nov 20, 2017, at 10:09 AM, Drew Crawford via swift-evolution 
>> > wrote:
>> 
>> The typical case for this function in my code is the identity closure, that 
>> is
>> 
>> let a: [Int?] = ...
>> print(a.filterMap {$0})
>> 
>> filterMap is quite poor for this situation because *each* component in the 
>> term is inaccurate:
> 
> filterMap is indeed an awkward name for this use case, just like flatMap is. 
> In my experience, about half of my use cases use the identity closure, and 
> half actually make use of the closure in a meaningful way. I would support a 
> proposal to add something like Sequence.dropNils (actual name to be 
> determined), and then we could let this proposal target the 
> non-identity-closure use case.
> 
> -BJ
> 
> ___
> 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-17 Thread Jonathan Hull via swift-evolution
Just to play devil’s advocate, wouldn’t they see random(in:) in the 
autocomplete when typing ‘random’?

Thanks,
Jon

> On Nov 17, 2017, at 3:09 PM, Xiaodi Wu via swift-evolution 
>  wrote:
> 
> On Fri, Nov 17, 2017 at 10:10 AM, Gwendal Roué via swift-evolution 
> > wrote:
> 
> > Le 17 nov. 2017 à 16:04, Alejandro Alonso via swift-evolution 
> > > a écrit :
> >
> > If we go back to your example, you never call FixedWidthInteger.random 
> > either, you call range.random. Does this mean integer types shouldn’t have 
> > .random? No, because it means get a random number from it’s internal range 
> > (alias to (min ... max).random). I think we can all agree that 
> > Integer.random is a nicer api than making a range of its bounds. The same 
> > goes for Date.random and Color.random.
> >
> > - Alejandro
> 
> Hello,
> 
> I'm not random expert, but it has never happened in my developer life 
> (backend & frontend app developer) that I have used a pure random value from 
> the full domain of the random type. In this life:
> 
> - Int.random is _always_ followed by % modulo. Unless the better 
> arc4random_uniform(max) is used.
> - Color.random is _never_ used, because random colors look bad.
> - Date.random is _never_ used, because time is a physical unit, and random 
> points in time do not match any physical use case.
> 
> This does not mean that random values from the full domain are useless. Of 
> course not: math apps, fuzzers, etc. need them.
> 
> Yet a range-based API would be much welcomed by regular app developers. And 
> also Array.randomElement(), Array.shuffled(), etc, because there are plenty 
> naive and bad algorithms for those simple tasks.
> 
> Certainly it's hard to defend Date.random (and yes, it might be useful for a 
> fuzzer, but that's a very niche use case--and in that case the fuzzer should 
> probably also generate invalid/non-existent dates, which surely Date.random 
> should not do). But actually, Int.random followed by % is the much bigger 
> issue and a very good cautionary tale for why T.random is not a good idea. 
> Swift should help users do the correct thing, and getting a random value 
> across the full domain and computing an integer modulus is never the correct 
> thing to do because of modulo bias, yet it's a very common error to make. We 
> are much better off eliminating this API and encouraging use of the correct 
> API, thereby reducing the likelihood of users making this category of error.
> 
> If (and I agree with this) the range-based notation is less intuitive 
> (0..<10.random is certainly less discoverable than Int.random), then we ought 
> to offer an API in the form of `Int.random(in:)` but not `Int.random`. This 
> does not preclude a `Collection.random` API as Alejandro proposes, of course, 
> and that has independent value as Gwendal says.
>  
> ___
> swift-evolution mailing list
> swift-evolution@swift.org 
> https://lists.swift.org/mailman/listinfo/swift-evolution 
> 
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] update on forum

2017-11-09 Thread Jonathan Hull via swift-evolution
Glad to see there is progress on this :-)

I am hoping, in addition to sections equivalent to the lists, there are areas 
for working groups on specific topics, and areas for 3rd party 
frameworks/packages to coordinate/cross-polinate ideas.  For example, I have 
code which I use as a more powerful (and easier to use) form of “bindings” 
which I am considering cleaning up and open sourcing. It would be nice to have 
a place on the forums where I could ask if others were interested in helping 
with that effort (or even just had advice for it). None of the lists seem to be 
right for that right now...

Thanks,
Jon 

> On Nov 9, 2017, at 6:13 AM, Ted Kremenek via swift-evolution 
>  wrote:
> 
> The decision to move to a forum was announced a while ago, and it hasn’t 
> appeared yet.  I think we will be making the move soon and I wanted to 
> provide some reasons why it was delayed and what comes next.
> 
> The reasons it was delayed are twofold:
> 
> -  When we (the community) decided to move to a forum there was plenty of 
> other planned infrastructure work that was in the works that took immediate 
> priority (such as the source compatibility suite and supporting Swift 4 
> development).
> 
> - In August (when Swift 4 was wrapping up) my team at Apple seriously picked 
> up the topic of the forum again and started looking in how to make it happen. 
>  At that point, a bunch of unexpected delays, one after the other, happened.  
> I can’t share these details (they are mostly non-technical) and going through 
> them would come off as me making a bunch of excuses anyway.  I do realize the 
> forum has been promised and not yet delivered for some time, and I know how 
> frustrating that is to the community.
> 
> Here’s what happens next:
> 
> - We plan on having the company behind Discourse.org  
> host the forums.  We’re wrapping up the remaining steps to issue a PO, but my 
> hope is to get that all done within the next couple weeks.  Thanksgiving in 
> the USA may delay that to the beginning of December.
> 
> - My understanding is the forum will still have a swift.org 
>  address, so the hosting is just an implementation detail.
> 
> - The company hosting Discourse.org  will migrate the 
> existing mailing list archives over to the new forum.  One thing we will need 
> to figure out (possibly as a community?) are specific requirements we have in 
> place for that migration.  The new forums don’t have to exactly mirror how 
> the mailing lists are structured today, and part of the reason to move to the 
> forum was motivated by having new opportunities to structure conversations.
> 
> I suspect there will be some trial and error with moving over the existing 
> mailing lists to the new forum, and I don’t have a good feel on how long that 
> will take.  However, once we reach that stage, it should be very transparent 
> to the community what exactly is going on.  My hope is that process will 
> start in December.
> 
> Ted
> ___
> 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] [pitch] Eliminate Collection.IndexDistance associated type

2017-11-08 Thread Jonathan Hull via swift-evolution
I guess I am mildly +1.  I can’t think of a case where this wouldn’t be some 
sort of Integer, but I am also open to arguments against.  I am not sure what 
the utility of having a type for this besides Int is...

Thanks,
Jon

> On Nov 8, 2017, at 1:37 PM, Ben Cohen via swift-evolution 
>  wrote:
> 
> 
> Hi Swift Evolution,
> 
> A pitch for review, aimed at simplifying generic Collection algorithms.
> 
> Online copy here:
> 
> https://github.com/airspeedswift/swift-evolution/blob/5d1ffda2e83f5b95a88d5ce3948c5fd0d59622f4/proposals/-eliminate-indexdistance.md
>  
> 
> 
> # Eliminate `IndexDistance` from `Collection`
> 
> * Proposal: [SE-](-eliminate-indexdistance.md)
> * Authors: [Ben Cohen](https://github.com/airspeedswift 
> )
> * Review Manager: TBD
> * Status: **Awaiting review**
> * Implementation: 
> [apple/swift#12641](https://github.com/apple/swift/pull/12641 
> )
> 
> ## Introduction
> 
> Eliminate the associated type `IndexDistance` from `Collection`, and modify 
> all uses to the concrete type `Int` instead.
> 
> ## Motivation
> 
> `Collection` allows for the distance between two indices to be any 
> `SignedInteger` type via the `IndexDistance` associated type. While in 
> practice the distance between indices is almost always
> an `Int`, generic algorithms on `Collection` need to either constrain 
> `IndexDistance == Int`, or write their algorithm to be generic over any 
> `SignedInteger`.
> 
> Swift 4.0 introduced the ability to constrain associated types with `where` 
> clauses
> ([SE-142](https://github.com/apple/swift-evolution/blob/master/proposals/0142-associated-types-constraints.md
>  
> ))
>  and will soon allow protocol constraints
> to be recursive 
> ([SE-157](https://github.com/apple/swift-evolution/blob/master/proposals/0157-recursive-protocol-constraints.md
>  
> )).
>  With these features,
> writing generic algorithms against `Collection` is finally a realistic tool 
> for intermediate Swift programmers. You no longer need to know to
> constrain `SubSequence.Element == Element` or `SubSequence: Collection`, 
> missing constraints that previously led to inexplicable error messages.
> 
> At this point, the presence of `IndexDistance` is of of the biggest hurdles 
> that new users trying to write generic algorithms face. If you want to
> write code that will compile against any distance type, you need to 
> constantly juggle with explicit type annotations (i.e. you need to write `let 
> i:
> IndexDistance = 0` instead of just `let i = 0`), and perform `numericCast` to 
> convert from one distance type to another.
> 
> But these `numericCasts` are hard to use correctly. Given two collections 
> with different index distances, it's very hard to reason about whether your
> `numericCast` is casting from the smaller to larger type correctly. This 
> turns any problem of writing a generic collection algorithm into both a 
> collection _and_
> problem. And chances are you are going to need to interoperate with a method 
> that takes or provides a concrete `Int` anyway (like `Array.reserveCapacity` 
> inside
> `Collection.map`). Much of the generic code in the standard library would 
> trap if ever presented with a collection with a distance greater than 
> `Int.max`.
> Additionally, this generalization makes specialization less likely and 
> increases compile-time work.
> 
> For these reasons, it's common to see algorithms constrained to 
> `IndexDistance == Int`. In fact, the inconvenience of having to deal with 
> generic index
> distances probably encourages more algorithms to be constrained to `Index == 
> Int`, such as [this
> code](https://github.com/airspeedswift/swift-package-manager/blob/472c647dcad3adf4344a06ef7ba91d2d4abddc94/Sources/Basic/OutputByteStream.swift#L119
>  
> )
>  in
> the Swift Package Manager. Converting this function to work with any index 
> type would be straightforward. Converting it to work with any index distance
> as well would be much trickier.
> 
> The general advice from [The Swift Programming
> Language](https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html#//apple_ref/doc/uid/TP40014097-CH5-ID309
>  
> )
>  when writing Swift code is to 

Re: [swift-evolution] [Review] SE-0187: Introduce Sequence.filterMap(_:)

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

> On Nov 7, 2017, at 3:23 PM, John McCall via swift-evolution 
>  wrote:
> 
> When writing your review, here are some questions you might want to answer in 
> your review:
> 
>   • What is your evaluation of the proposal?

-1.  I am indifferent on the name, but don’t think it is worth the code churn.

What I would much rather see is an attribute that could be placed on parameters 
that would prevent optional promotion in those cases.  That would prevent the 
issue listed here without needing to change the name, and it would be helpful 
in other places where optional promotion could cause mistakes.


>   • Is the problem being addressed significant enough to warrant a change 
> to Swift?

No, I don’t really think so.

>   • Does this proposal fit well with the feel and direction of Swift?

Meh.  I think both the current name and the proposed name fit within the feel 
of swift.

>   • If you have used other languages or libraries with a similar feature, 
> how do you feel that this proposal compares to those?

There are a lot of languages with this functionality, they all have slightly 
different names for it. I think the name is fine, but if the name had been 
filterMap to start with that would have been ok too.  I don’t think it is worth 
changing at this point though.

>   • How much effort did you put into your review? A glance, a quick 
> reading, or an in-depth study?

I followed the discussion, but didn’t spend a great deal of time thinking about 
it beyond that.___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Large Proposal: Non-Standard Libraries

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

> On Nov 7, 2017, at 1:58 PM, Ted Kremenek via swift-evolution 
>  wrote:
> 
> We could also figure out a way to possibly highlight these efforts to the 
> Swift community, maybe on swift-evolution or other means — but all with the 
> expectation that these libraries are not *necessarily* going to be 
> standardized as part of the core swift distribution.  I don’t think that’s 
> all that bad either; not every library will make sense to incorporate into 
> the core Swift distribution (e.g., they are highly domain specific) but still 
> supporting their development would be beneficial to the community.

What I really want to see is a Code Store in Xcode (kind of like an app store 
for Swift packages).  Basically, you would hit “Add Package” in the 
sidebar/menu and a sheet pops up where you can search for and view various 
packages.  You then hit an “Add” button in the sheet, and it would add the 
package to your project.  To remove a package you would select it and hit 
delete.

Selecting a package in the sidebar would let you set some settings (e.g. select 
a specific version), and view documentation.  Xcode would manage the files for 
you behind the scenes.

I know that is out of scope for Evolution, but I just wanted to mention it, 
since it might help with the visibility issue.

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-05 Thread Jonathan Hull via swift-evolution
Is there a link to the writeup?  The one in the quote 404s.

Thanks,
Jon

> On Nov 5, 2017, at 2:10 PM, Alejandro Alonso via swift-evolution 
>  wrote:
> 
> Hello once again Swift evolution community. I have taken the time to write up 
> the proposal for this thread, and have provided an implementation for it as 
> well. I hope to once again get good feedback on the overall proposal.
> 
> - Alejandro
> 
> On Sep 8, 2017, 11:52 AM -0500, Alejandro Alonso via swift-evolution 
> , 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] stack classes

2017-10-27 Thread Jonathan Hull via swift-evolution
Could you explain more about your use case?  I am not sure I understand the 
motivation…

Also, what are you hoping to dealloc in structs?

Thanks,
Jon

> On Oct 27, 2017, at 6:27 AM, Mike Kluev via swift-evolution 
>  wrote:
> 
> if it wasn't already discussed here is the preliminary proposal, if it was 
> then my +1 to the feature.
> 
> i propose we have an explicit apparatus to denote classes having stack 
> storage.
> 
> stack class StackObject { // guaranteed to be on stack
> }
> 
> class NonStackObject { // is not guaranteed to be on stack, can be on heap as 
> well
> }
> 
> this is for performance reasons. sometimes what we need is “structs with 
> deinit” and as this is not going to happen the next best thing could be 
> “lightweight” classes. this shall be self obvious, here are few examples:
> 
> stack class StackObject {
> var variable = 0
> 
> func foo() {
> print(“i am ok to live on stack”)
> }
> }
> 
> stack class BadObject {
> var variable = 0
> 
> func foo() {
> DispatchQueue.main.async {  // error: can’t be a stack class
> self.variable = 1
> }
> }
> }
> 
> class NonStackObject {
> …
> }
> 
> foo() {
> let stackObject = StackObject()
> 
> DispatchQueue.main.async {
> stackObject.foo()  // error: can’t use a stack object in this context
> }
> }
> 
> ___
> 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] Pitch: Member lookup on String should not find members of NSString

2017-10-24 Thread Jonathan Hull via swift-evolution
I would feel better about it if String gained a lot of the utility of NSString 
(so that we don’t have to go to NSString all the time for methods)

Thanks,
Jon

> On Oct 24, 2017, at 3:00 PM, Slava Pestov via swift-evolution 
>  wrote:
> 
> Hi,
> 
> Members of NSString, except those defined in Foundation, are available on 
> values of type String. For example,
> 
> extension NSString {
>  @objc func foo() {}
> }
> 
> let s: String = “hello”
> 
> s.foo()
> 
> We don’t do this for any other bridged types, for instance NSArray methods 
> are not imported as Array methods. It’s literally a special case in the type 
> checker for member lookup on String.
> 
> This behavior doesn’t really much sense conceptually and it was put in as a 
> stop-gap in Swift 1 to beef up the String API. I would like to phase it out 
> as follows:
> 
> - Unconditional warning in Swift 4.1, with a fixit to insert an ‘as NSString’ 
> cast
> - Error in Swift 5 with -swift-version 5
> 
> What does everyone think about this?
> 
> Slava
> ___
> 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] [Draft] Rename Sequence.elementsEqual

2017-10-17 Thread Jonathan Hull via swift-evolution
Also of interest to this discussion is the following from a discussion on C#’s 
version of Set:

> HashSet is more or less modeled after a mathematical set 
> , which means that:
> 
> It may contain no duplicate values.
> Its elements are in no particular order; therefore the type does not 
> implement the IList 
> interface, but the 
> more basic ICollection 
> . As a consequence, 
> elements inside a hash set cannot be randomly accessed through indices; they 
> can only be iterated over through an enumerator.
So, it appears that C#/.Net does in fact take into account the fact that Sets 
are unordered, and only allows it to be iterated (as opposed to accessed with 
indices).

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


Re: [swift-evolution] [Draft] Rename Sequence.elementsEqual

2017-10-17 Thread Jonathan Hull via swift-evolution

> On Oct 17, 2017, at 11:46 AM, Xiaodi Wu  wrote:
> 
> 
> On Tue, Oct 17, 2017 at 12:54 Jonathan Hull  > wrote:
>> On Oct 17, 2017, at 9:34 AM, Xiaodi Wu > > wrote:
>> 
>> 
>> On Tue, Oct 17, 2017 at 09:42 Jonathan Hull > > wrote:
>>> On Oct 17, 2017, at 5:44 AM, Xiaodi Wu >> > wrote:
>>> 
>>> 
>>> On Tue, Oct 17, 2017 at 00:56 Thorsten Seitz >> > wrote:
>>> 
>>> 
>>> Am 17.10.2017 um 00:13 schrieb Xiaodi Wu >> >:
>>> 
 
 On Mon, Oct 16, 2017 at 14:21 Thorsten Seitz > wrote:
> Am 16.10.2017 um 16:20 schrieb Xiaodi Wu via swift-evolution 
> >:
> 
> 
> On Mon, Oct 16, 2017 at 05:48 Jonathan Hull  > wrote:
> 
>> On Oct 15, 2017, at 9:58 PM, Xiaodi Wu > > wrote:
>> 
>> On Sun, Oct 15, 2017 at 8:51 PM, Jonathan Hull > > wrote:
>> 
>>> On Oct 14, 2017, at 10:48 PM, Xiaodi Wu >> > wrote:
>  That ordering can be arbitrary, but it shouldn’t leak internal 
> representation such that the method used to create identical things 
> affects the outcome of generic methods because of differences in 
> internal representation.
> 
> 
>>  It would be better to say that the iteration order is well-defined. 
>> That will almost always mean documented, and usually predictable 
>> though obviously e.g. RNGs and iterating in random order will not be 
>> predictable by design.
>> 
>>> That's actually more semantically constrained than what Swift calls 
>>> a `Collection` (which requires conforming types to be multi-pass 
>>> and(?) finite). By contrast, Swift's `SpongeBob` protocol 
>>> explicitly permits conforming single-pass, infinite, and/or 
>>> unordered types. 
>> 
>> I think you’re talking about Sequence here, I’ve lost track of your 
>> nonsense by now. Yes, the current Swift protocol named Sequence 
>> allows unordered types. You seem to keep asserting that but not 
>> actually addressing my argument, which is that allowing Sequences to 
>> be unordered with the current API is undesired and actively harmful, 
>> and should therefore be changed.
>> 
>> What is harmful about it?
> 
> After thinking about it, I think the harmful bit is that unordered 
> sequences are leaking internal representation (In your example, this 
> is causing people to be surprised when two sets with identical 
> elements are generating different sequences/orderings based on how 
> they were created).  You are correct when you say that this problem 
> is even true for for-in.
> 
> I would not say it is a problem. Rather, by definition, iteration 
> involves retrieving one element after another; if you're allowed to 
> do that with Set, then the elements of a Set are observably ordered 
> in some way. Since it's not an OrderedSet--i.e., order doesn't 
> matter--then the only sensible conclusion is that the order of 
> elements obtained in a for...in loop must be arbitrary. If you think 
> this is harmful, then you must believe that one should be prohibited 
> from iterating over an instance of Set. Otherwise, Set is inescapably 
> a Sequence by the Swift definition of Sequence. All extension methods 
> on Sequence like drop(while:) are really just conveniences for common 
> things that you can do with iterated access; to my mind, they're 
> essentially just alternative ways of spelling various for...in loops.
 
 I think an argument could be made that you shouldn’t be able to 
 iterate over a set without first defining an ordering on it (even if 
 that ordering is somewhat arbitrary).  Maybe we have something like a 
 “Sequenc(e)able” protocol which defines things which can be turned 
 into a sequence when combined with some sort of ordering.  One 
 possible ordering could be the internal representation (At least in 
 that case we are calling it out specifically).  If I had to say 
 “setA.arbitraryOrder.elementsEqual(setB.arbitraryOrder)” I would 
 definitely be less surprised when it returns false even though setA == 
 setB.
 
 

Re: [swift-evolution] [Draft] Rename Sequence.elementsEqual

2017-10-17 Thread Jonathan Hull via swift-evolution

> On Oct 17, 2017, at 11:47 AM, Michael Ilseman via swift-evolution 
>  wrote:
> 
> `==` conveys substitutability of the two Sequences. This does not necessarily 
> entail anything about their elements, how those elements are ordered, etc., 
> it just means two Sequences are substitutable. `elementsEqual` means that the 
> two Sequences produce substitutable elements. These are different concepts 
> and both are independently useful.

I agree that ‘==‘ conveys substitutability.  Here is the issue:

let a = Set([1,2,3,4,5])
let b = Set([5,4,3,2,1])

a == b //True, they are substitutable

[1,2,3,4,5].elementsEqual(a) //True
[1,2,3,4,5].elementsEqual(b) //False… I guess they weren’t actually 
substitutable after all


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


Re: [swift-evolution] [Draft] Rename Sequence.elementsEqual

2017-10-17 Thread Jonathan Hull via swift-evolution

> On Oct 17, 2017, at 9:34 AM, Xiaodi Wu  wrote:
> 
> 
> On Tue, Oct 17, 2017 at 09:42 Jonathan Hull  > wrote:
>> On Oct 17, 2017, at 5:44 AM, Xiaodi Wu > > wrote:
>> 
>> 
>> On Tue, Oct 17, 2017 at 00:56 Thorsten Seitz > > wrote:
>> 
>> 
>> Am 17.10.2017 um 00:13 schrieb Xiaodi Wu > >:
>> 
>>> 
>>> On Mon, Oct 16, 2017 at 14:21 Thorsten Seitz >> > wrote:
 Am 16.10.2017 um 16:20 schrieb Xiaodi Wu via swift-evolution 
 >:
 
 
 On Mon, Oct 16, 2017 at 05:48 Jonathan Hull > wrote:
 
> On Oct 15, 2017, at 9:58 PM, Xiaodi Wu  > wrote:
> 
> On Sun, Oct 15, 2017 at 8:51 PM, Jonathan Hull  > wrote:
> 
>> On Oct 14, 2017, at 10:48 PM, Xiaodi Wu > > wrote:
  That ordering can be arbitrary, but it shouldn’t leak internal 
 representation such that the method used to create identical things 
 affects the outcome of generic methods because of differences in 
 internal representation.
 
 
>  It would be better to say that the iteration order is well-defined. 
> That will almost always mean documented, and usually predictable 
> though obviously e.g. RNGs and iterating in random order will not be 
> predictable by design.
> 
>> That's actually more semantically constrained than what Swift calls 
>> a `Collection` (which requires conforming types to be multi-pass 
>> and(?) finite). By contrast, Swift's `SpongeBob` protocol explicitly 
>> permits conforming single-pass, infinite, and/or unordered types. 
> 
> I think you’re talking about Sequence here, I’ve lost track of your 
> nonsense by now. Yes, the current Swift protocol named Sequence 
> allows unordered types. You seem to keep asserting that but not 
> actually addressing my argument, which is that allowing Sequences to 
> be unordered with the current API is undesired and actively harmful, 
> and should therefore be changed.
> 
> What is harmful about it?
 
 After thinking about it, I think the harmful bit is that unordered 
 sequences are leaking internal representation (In your example, this 
 is causing people to be surprised when two sets with identical 
 elements are generating different sequences/orderings based on how 
 they were created).  You are correct when you say that this problem is 
 even true for for-in.
 
 I would not say it is a problem. Rather, by definition, iteration 
 involves retrieving one element after another; if you're allowed to do 
 that with Set, then the elements of a Set are observably ordered in 
 some way. Since it's not an OrderedSet--i.e., order doesn't 
 matter--then the only sensible conclusion is that the order of 
 elements obtained in a for...in loop must be arbitrary. If you think 
 this is harmful, then you must believe that one should be prohibited 
 from iterating over an instance of Set. Otherwise, Set is inescapably 
 a Sequence by the Swift definition of Sequence. All extension methods 
 on Sequence like drop(while:) are really just conveniences for common 
 things that you can do with iterated access; to my mind, they're 
 essentially just alternative ways of spelling various for...in loops.
>>> 
>>> I think an argument could be made that you shouldn’t be able to iterate 
>>> over a set without first defining an ordering on it (even if that 
>>> ordering is somewhat arbitrary).  Maybe we have something like a 
>>> “Sequenc(e)able” protocol which defines things which can be turned into 
>>> a sequence when combined with some sort of ordering.  One possible 
>>> ordering could be the internal representation (At least in that case we 
>>> are calling it out specifically).  If I had to say 
>>> “setA.arbitraryOrder.elementsEqual(setB.arbitraryOrder)” I would 
>>> definitely be less surprised when it returns false even though setA == 
>>> setB.
>>> 
>>> Well, that's a totally different direction, then; you're arguing that 
>>> `Set` and `Dictionary` should not conform to `Sequence` altogether. 
>>> That's fine (it's also a direction that some of us explored off-list a 
>>> while ago), but at this point in Swift's evolution, realistically, it's 

Re: [swift-evolution] [Draft] Rename Sequence.elementsEqual

2017-10-17 Thread Jonathan Hull via swift-evolution

> On Oct 17, 2017, at 5:44 AM, Xiaodi Wu  wrote:
> 
> 
> On Tue, Oct 17, 2017 at 00:56 Thorsten Seitz  > wrote:
> 
> 
> Am 17.10.2017 um 00:13 schrieb Xiaodi Wu  >:
> 
>> 
>> On Mon, Oct 16, 2017 at 14:21 Thorsten Seitz > > wrote:
>>> Am 16.10.2017 um 16:20 schrieb Xiaodi Wu via swift-evolution 
>>> >:
>>> 
>>> 
>>> On Mon, Oct 16, 2017 at 05:48 Jonathan Hull >> > wrote:
>>> 
 On Oct 15, 2017, at 9:58 PM, Xiaodi Wu > wrote:
 
 On Sun, Oct 15, 2017 at 8:51 PM, Jonathan Hull > wrote:
 
> On Oct 14, 2017, at 10:48 PM, Xiaodi Wu  > wrote:
>>>  That ordering can be arbitrary, but it shouldn’t leak internal 
>>> representation such that the method used to create identical things 
>>> affects the outcome of generic methods because of differences in 
>>> internal representation.
>>> 
>>> 
  It would be better to say that the iteration order is well-defined. 
 That will almost always mean documented, and usually predictable 
 though obviously e.g. RNGs and iterating in random order will not be 
 predictable by design.
 
> That's actually more semantically constrained than what Swift calls a 
> `Collection` (which requires conforming types to be multi-pass and(?) 
> finite). By contrast, Swift's `SpongeBob` protocol explicitly permits 
> conforming single-pass, infinite, and/or unordered types. 
 
 I think you’re talking about Sequence here, I’ve lost track of your 
 nonsense by now. Yes, the current Swift protocol named Sequence allows 
 unordered types. You seem to keep asserting that but not actually 
 addressing my argument, which is that allowing Sequences to be 
 unordered with the current API is undesired and actively harmful, and 
 should therefore be changed.
 
 What is harmful about it?
>>> 
>>> After thinking about it, I think the harmful bit is that unordered 
>>> sequences are leaking internal representation (In your example, this is 
>>> causing people to be surprised when two sets with identical elements 
>>> are generating different sequences/orderings based on how they were 
>>> created).  You are correct when you say that this problem is even true 
>>> for for-in.
>>> 
>>> I would not say it is a problem. Rather, by definition, iteration 
>>> involves retrieving one element after another; if you're allowed to do 
>>> that with Set, then the elements of a Set are observably ordered in 
>>> some way. Since it's not an OrderedSet--i.e., order doesn't 
>>> matter--then the only sensible conclusion is that the order of elements 
>>> obtained in a for...in loop must be arbitrary. If you think this is 
>>> harmful, then you must believe that one should be prohibited from 
>>> iterating over an instance of Set. Otherwise, Set is inescapably a 
>>> Sequence by the Swift definition of Sequence. All extension methods on 
>>> Sequence like drop(while:) are really just conveniences for common 
>>> things that you can do with iterated access; to my mind, they're 
>>> essentially just alternative ways of spelling various for...in loops.
>> 
>> I think an argument could be made that you shouldn’t be able to iterate 
>> over a set without first defining an ordering on it (even if that 
>> ordering is somewhat arbitrary).  Maybe we have something like a 
>> “Sequenc(e)able” protocol which defines things which can be turned into 
>> a sequence when combined with some sort of ordering.  One possible 
>> ordering could be the internal representation (At least in that case we 
>> are calling it out specifically).  If I had to say 
>> “setA.arbitraryOrder.elementsEqual(setB.arbitraryOrder)” I would 
>> definitely be less surprised when it returns false even though setA == 
>> setB.
>> 
>> Well, that's a totally different direction, then; you're arguing that 
>> `Set` and `Dictionary` should not conform to `Sequence` altogether. 
>> That's fine (it's also a direction that some of us explored off-list a 
>> while ago), but at this point in Swift's evolution, realistically, it's 
>> not within the realm of possible changes.
> 
> I am actually suggesting something slightly different.  Basically, Set 
> and Dictionary’s conformance to Collection would have a different 
> implementation.  They would conform to another protocol declaring that 
> they are 

Re: [swift-evolution] [Draft] Rename Sequence.elementsEqual

2017-10-17 Thread Jonathan Hull via swift-evolution

> On Oct 17, 2017, at 12:04 AM, Gwendal Roué via swift-evolution 
>  wrote:
> 
>>> Modeling is, by definition, imperfect. The question is, what imperfect 
>>> model is most useful _to Swift_. The idea is that conforming Set and 
>>> Dictionary to Collection is on balance more useful than not doing so; that 
>>> having two protocols, Sequence and Collection, is on balance more useful 
>>> than having one or three, and that the set of semantic guarantees of 
>>> Collection are on balance more useful than other possible sets of semantic 
>>> guarantees.
>> 
>> That is your idea which is disputed and underlined with arguments whereas 
>> you keep repeating that Set behaves as dictated by its conformance without 
>> giving use cases why this should be useful.
> 
> Hello,
> 
> You can't *control* the ordering of a set or a dictionary, but you can still 
> *rely* on it.
> 
> For example, to find a key in a dictionary that is associated a given value, 
> you can rely on the fact that a dictionary's order is guaranteed to be 
> stable, and that on top of that its indexes can address the dictionary 
> itself, but also its keys and values sequences. The code below has no bug;
> 
> let dict = ["a": "foo", "b": "bar", "c": "needle"]
> 
> // Find a key associated with "needle"
> if let index = dict.values.index(of: "needle") {
> let key = dict.keys[index]
> print(key) // prints "c"
> }

You are using the index from one collection to index into another collection.  
Isn’t that something the documentation explicitly tells us not to do?  Or is 
there a special (documented) guarantee that these collections will always sync 
indices?

I guess you could do:

if let key = dict.first(where {$1 == “needle}).0 {
print(key)
}

…although note that which element is “first” if there are multiple keys with 
needle as the value may shift around on you as you mess with the dictionary 
(and also on separate runs even if you don’t mess with the dictionary).

> It's more difficult to find a use case for set's ordering and indexes. But 
> since you ask, here is an example. The goal is to find any element which is 
> not equal to another value, in any collection:
> 
> extension Collection where Element: Equatable {
> /// Returns any element which is not equal to the given element
> func anyElement(notEqualTo v: Element) -> Element? {
> if let i = index(of: v) {
> if let alt = index(i, offsetBy: 1, limitedBy: endIndex), alt != 
> endIndex {
> return self[alt]
> }
> if i == startIndex {
> return nil
> }
> return first
> }
> return first
> }
> }
> 
> Set([1, 2, 3]).anyElement(notEqualTo: 1) // 2 or 3
> Set([1, 2]).anyElement(notEqualTo: 1)// 2
> Set([1]).anyElement(notEqualTo: 1)   // nil
> Set([2]).anyElement(notEqualTo: 1)   // 2
> Set([]).anyElement(notEqualTo: 1)// nil
> 
> That *can* be useful, isn't it?

Yes, although this could easily be provided using iteration without indexing.


Note that my current favorite solution is to simply provide an additional 
guarantee on set/dictionary that the iteration order will always be the same 
for the same contents (regardless of history), but the order would still be 
otherwise arbitrary.  That is a non-source-breaking change (renaming IS source 
breaking).  It won’t fix everything, but it will fix some of the biggest 
gotchas.  As a bonus, elementsEqual will 'just work'™ for sets/dictionaries. 

Thanks,
Jon


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


Re: [swift-evolution] [Draft] Rename Sequence.elementsEqual

2017-10-16 Thread Jonathan Hull via swift-evolution
To expand on this, Set([1,2,3,4,5]).hasPrefix([1,2,3]) currently returns true.  
But let’s say a year from now, we change Set to return an ordering based on 
hash values (which is entirely reasonable). Suddenly the same code may return 
true or false. 

No guarantees will be broken by doing that, but the result has still changed 
because we are building on top of undefined behavior. Collection says nothing 
about the ordering over different builds of a program.

Thanks,
Jon

> On Oct 16, 2017, at 4:11 PM, Jonathan Hull via swift-evolution 
> <swift-evolution@swift.org> wrote:
> 
>> 
>> On Oct 16, 2017, at 1:05 PM, Xiaodi Wu <xiaodi...@gmail.com 
>> <mailto:xiaodi...@gmail.com>> wrote:
>> 
>> 
>> On Mon, Oct 16, 2017 at 10:49 Jonathan Hull <jh...@gbis.com 
>> <mailto:jh...@gbis.com>> wrote:
>> 
>>> On Oct 16, 2017, at 7:20 AM, Xiaodi Wu <xiaodi...@gmail.com 
>>> <mailto:xiaodi...@gmail.com>> wrote:
>>> 
>>> To start with, the one you gave as an example at the beginning of this 
>>> discussion: Two sets with identical elements which have different internal 
>>> storage and thus give different orderings as sequences.  You yourself have 
>>> argued that the confusion around this is enough of a problem that we need 
>>> to make a source-breaking change (renaming it) to warn people that the 
>>> results of the ‘elementsEqual’ algorithm are undefined for sets and 
>>> dictionaries.
>>> 
>>> No, I am arguing that the confusion about ‘elementsEqual’ is foremost a 
>>> problem with its name; the result of this operation is not at all undefined 
>>> for two sets but actually clearly defined: it returns true if two sets have 
>>> the same elements in the same iteration order, which is a publicly 
>>> observable behavior of sets (likewise dictionaries).
>> 
>> But that iteration order is undefined and could easily change due to changes 
>> in the private/internal structure of sets/dictionaries.  Algorithms that 
>> rely on that “publicly observable behavior” (i.e. leaking of internals) will 
>> suddenly break.
>> 
>> And an algorithm in which such “sudden breakage” would occur is…?
> 
> Here are a few off the top of my head:
> 
> func hasPrefix(Sequence)->Bool
> func hasSuffix(Sequence)->Bool
> func containsSubsequence(Sequence)->Bool
> 
> What do these methods mean with regards to Set’s “publicly observable 
> behavior”?
> 
>> 
>> You keep claiming that this bug is a feature because it is the current 
>> behavior… but that is tautological reasoning.
>> 
>> Thanks,
>> Jon
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
> https://lists.swift.org/mailman/listinfo/swift-evolution 
> <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] [Draft] Rename Sequence.elementsEqual

2017-10-16 Thread Jonathan Hull via swift-evolution

> On Oct 16, 2017, at 1:05 PM, Xiaodi Wu  wrote:
> 
> 
> On Mon, Oct 16, 2017 at 10:49 Jonathan Hull  > wrote:
> 
>> On Oct 16, 2017, at 7:20 AM, Xiaodi Wu > > wrote:
>> 
>> To start with, the one you gave as an example at the beginning of this 
>> discussion: Two sets with identical elements which have different internal 
>> storage and thus give different orderings as sequences.  You yourself have 
>> argued that the confusion around this is enough of a problem that we need to 
>> make a source-breaking change (renaming it) to warn people that the results 
>> of the ‘elementsEqual’ algorithm are undefined for sets and dictionaries.
>> 
>> No, I am arguing that the confusion about ‘elementsEqual’ is foremost a 
>> problem with its name; the result of this operation is not at all undefined 
>> for two sets but actually clearly defined: it returns true if two sets have 
>> the same elements in the same iteration order, which is a publicly 
>> observable behavior of sets (likewise dictionaries).
> 
> But that iteration order is undefined and could easily change due to changes 
> in the private/internal structure of sets/dictionaries.  Algorithms that rely 
> on that “publicly observable behavior” (i.e. leaking of internals) will 
> suddenly break.
> 
> And an algorithm in which such “sudden breakage” would occur is…?

Here are a few off the top of my head:

func hasPrefix(Sequence)->Bool
func hasSuffix(Sequence)->Bool
func containsSubsequence(Sequence)->Bool

What do these methods mean with regards to Set’s “publicly observable behavior”?

> 
> You keep claiming that this bug is a feature because it is the current 
> behavior… but that is tautological reasoning.
> 
> Thanks,
> Jon

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


Re: [swift-evolution] [Draft] Rename Sequence.elementsEqual

2017-10-16 Thread Jonathan Hull via swift-evolution

> On Oct 16, 2017, at 7:20 AM, Xiaodi Wu  wrote:
> 
> To start with, the one you gave as an example at the beginning of this 
> discussion: Two sets with identical elements which have different internal 
> storage and thus give different orderings as sequences.  You yourself have 
> argued that the confusion around this is enough of a problem that we need to 
> make a source-breaking change (renaming it) to warn people that the results 
> of the ‘elementsEqual’ algorithm are undefined for sets and dictionaries.
> 
> No, I am arguing that the confusion about ‘elementsEqual’ is foremost a 
> problem with its name; the result of this operation is not at all undefined 
> for two sets but actually clearly defined: it returns true if two sets have 
> the same elements in the same iteration order, which is a publicly observable 
> behavior of sets (likewise dictionaries).

But that iteration order is undefined and could easily change due to changes in 
the private/internal structure of sets/dictionaries.  Algorithms that rely on 
that “publicly observable behavior” (i.e. leaking of internals) will suddenly 
break.  You keep claiming that this bug is a feature because it is the current 
behavior… but that is tautological reasoning.

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


Re: [swift-evolution] [Draft] Rename Sequence.elementsEqual

2017-10-15 Thread Jonathan Hull via swift-evolution
Ok, just to summarize our options so far (in order of effort & theoretical 
effectiveness):

1) Do nothing - This is the easiest thing to do, but it won’t fix any problems

2) Rename the elementsEqual method: (Again, fairly easy to do, and will 
hopefully reduce confusion, but doesn’t fix the underlying issue)
• lexicographicallyEquals
• elementOrderingEqual (this is my favorite of the names)
• sequentiallyEquals
• orderedEqual
• pairwiseEqual
• iterativelyEquals
I might be missing some...

3) Change the implementation of Set so that it will return the same order 
whenever it has the same elements. This solves the issue with set, but not with 
unordered sequences in general (e.g. comparing a set with the keys of a 
dictionary). Still on balance, this is my current favorite.

4) Add an UnorderedX (name to be bikeshed) protocol that defines a 
sequence/collection as unordered, which provides a method which will return a 
sequence/collection of defined order. Generic algorithms can check for 
conformance to the UnorderedX protocol, and provide different implementations 
as needed (mostly by operating on the provided sequence/collection).  The 
advantage is that generic algorithms can be made which take whether the 
sequence is ordered/unordered into account, and we don’t lose any speed. The 
downside is that you have to remember to check if it is ordered or not, and 
failing to do so may result in generic algorithms which have the current 
issues.  We could guarantee that the standard library would be correct though.

5) Add an UnorderedX protocol that defines a sequence/collection as unordered, 
takes the unordered elements and uses them to provide a partial implementation 
to Sequence/Collection where the elements have a defined order.  The advantage 
to this is that you can now build correct generic algorithms that depend on a 
stable/defined ordering that will “just work" (e.g. elementsEqual will work 
when comparing a set to the keys of a dictionary).  The disadvantage is that it 
will be a bit slower for things that don’t care about ordering (e.g. many 
things involving for-in) unless you specifically call a method that says you 
don’t care about the order.

6) Rework the Sequence protocols to account for Ordered and Unordered (e.g. 
replacing ‘first’ with ‘any’ and then adding ‘first’ back in only for ordered 
sequences).  Reworking the protocol hierarchy would be the most permanent and 
theoretically “correct” fix, but has the potential to be massively 
source-breaking.


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


Re: [swift-evolution] [Draft] Rename Sequence.elementsEqual

2017-10-15 Thread Jonathan Hull via swift-evolution

> On Oct 14, 2017, at 10:48 PM, Xiaodi Wu  wrote:
>>>  That ordering can be arbitrary, but it shouldn’t leak internal 
>>> representation such that the method used to create identical things affects 
>>> the outcome of generic methods because of differences in internal 
>>> representation.
>>> 
>>> 
  It would be better to say that the iteration order is well-defined. That 
 will almost always mean documented, and usually predictable though 
 obviously e.g. RNGs and iterating in random order will not be predictable 
 by design.
 
> That's actually more semantically constrained than what Swift calls a 
> `Collection` (which requires conforming types to be multi-pass and(?) 
> finite). By contrast, Swift's `SpongeBob` protocol explicitly permits 
> conforming single-pass, infinite, and/or unordered types. 
 
 I think you’re talking about Sequence here, I’ve lost track of your 
 nonsense by now. Yes, the current Swift protocol named Sequence allows 
 unordered types. You seem to keep asserting that but not actually 
 addressing my argument, which is that allowing Sequences to be unordered 
 with the current API is undesired and actively harmful, and should 
 therefore be changed.
 
 What is harmful about it?
>>> 
>>> After thinking about it, I think the harmful bit is that unordered 
>>> sequences are leaking internal representation (In your example, this is 
>>> causing people to be surprised when two sets with identical elements are 
>>> generating different sequences/orderings based on how they were created).  
>>> You are correct when you say that this problem is even true for for-in.
>>> 
>>> I would not say it is a problem. Rather, by definition, iteration involves 
>>> retrieving one element after another; if you're allowed to do that with 
>>> Set, then the elements of a Set are observably ordered in some way. Since 
>>> it's not an OrderedSet--i.e., order doesn't matter--then the only sensible 
>>> conclusion is that the order of elements obtained in a for...in loop must 
>>> be arbitrary. If you think this is harmful, then you must believe that one 
>>> should be prohibited from iterating over an instance of Set. Otherwise, Set 
>>> is inescapably a Sequence by the Swift definition of Sequence. All 
>>> extension methods on Sequence like drop(while:) are really just 
>>> conveniences for common things that you can do with iterated access; to my 
>>> mind, they're essentially just alternative ways of spelling various 
>>> for...in loops.
>> 
>> I think an argument could be made that you shouldn’t be able to iterate over 
>> a set without first defining an ordering on it (even if that ordering is 
>> somewhat arbitrary).  Maybe we have something like a “Sequenc(e)able” 
>> protocol which defines things which can be turned into a sequence when 
>> combined with some sort of ordering.  One possible ordering could be the 
>> internal representation (At least in that case we are calling it out 
>> specifically).  If I had to say 
>> “setA.arbitraryOrder.elementsEqual(setB.arbitraryOrder)” I would definitely 
>> be less surprised when it returns false even though setA == setB.
>> 
>> Well, that's a totally different direction, then; you're arguing that `Set` 
>> and `Dictionary` should not conform to `Sequence` altogether. That's fine 
>> (it's also a direction that some of us explored off-list a while ago), but 
>> at this point in Swift's evolution, realistically, it's not within the realm 
>> of possible changes.
> 
> I am actually suggesting something slightly different.  Basically, Set and 
> Dictionary’s conformance to Collection would have a different implementation. 
>  They would conform to another protocol declaring that they are unordered. 
> That protocol would fill in part of the conformance to sequence/collection 
> using a default ordering, which is mostly arbitrary, but guaranteed to 
> produce the same ordering for the same list of elements (even across 
> collection types).  This would be safer, but a tiny bit slower than what we 
> have now (We could also potentially develop a way for collections like set to 
> amortize the cost). For those who need to recover speed, the new protocol 
> would also define a property which quickly returns a sequence/iterator using 
> the internal ordering (I arbitrarily called it .arbitraryOrder).
> 
> I believe it would not be source breaking.
> 
> That is indeed something slightly different.
> 
> In an ideal world--and my initial understanding of what you were 
> suggesting--Set and Dictionary would each have a member like `collection`, 
> which would expose the underlying data as a `SetCollection` or 
> `DictionaryCollection` that in turn would conform to `Collection`; meanwhile, 
> Set and Dictionary themselves would not offer methods such as `prefix`, or 
> indexing by subscript, which are not compatible with being unordered. For 
> those who want a 

Re: [swift-evolution] [Draft] Rename Sequence.elementsEqual

2017-10-15 Thread Jonathan Hull via swift-evolution

> On Oct 15, 2017, at 3:41 PM, Xiaodi Wu via swift-evolution 
>  wrote:
> 
> I’ll have to mull this over to see if I can come up with a coherent and 
> (more) specific requirement for what makes an Iterable a Sequence, since 
> clearly “documented” isn’t enough.  Perhaps something along the lines that 
> any two Sequences that compare equal must iterate the same.
> 
>> […]
>> Apple documentation calls this one of the "order-dependent" methods. It is 
>> surely acceptable for a type that conforms to an order-dependent protocol to 
>> have methods that are order-dependent; they do, however, have to be clearly 
>> order-dependent to avoid confusion on unordered types.
> 
> I’m not clear on what you’re trying to get across here. It seems you’re 
> saying unordered types shouldn’t have order-dependent methods, which is 
> exactly what I’ve been arguing.
> 
> No, I'm saying, essentially, that there are no truly unordered types in 
> Swift; `Set` and `Dictionary` lead double lives modeling unordered 
> collections on the one hand and ordered collections on the other. The 
> order-dependent methods can continue to exist; they just need to be clearly 
> named so that users know when they're using an instance of `Set` in the 
> manner of an unordered collection and when they're using an instance of `Set` 
> in the manner of an ordered collection.

Is the order of elements returned from Set/Dictionary guaranteed not to change 
based on implementation?  For instance, the elements of a dictionary may shift 
around as I add items, and they may be different in different runs of a program.

If we document/say that Set will always return elements in the order they were 
added, then it may prevent us from using a more efficient implementation of 
Sets in a future version of Swift.

Just to check what we are saying.  I am saying that we can’t really build 
generic algorithms on something which is undefined (because we are leaking 
implementation details, and depending on private implementation details leads 
to problems).  You are saying that the leaking of implementation details is a 
feature, not a bug… and that we should just document them and consider them 
fixed ABI?

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


Re: [swift-evolution] [Draft] Rename Sequence.elementsEqual

2017-10-14 Thread Jonathan Hull via swift-evolution

> On Oct 14, 2017, at 9:59 PM, Xiaodi Wu  wrote:
> 
> On Sat, Oct 14, 2017 at 11:48 PM, Jonathan Hull  > wrote:
> 
>> On Oct 14, 2017, at 9:21 PM, Xiaodi Wu > > wrote:
>> 
>> On Sat, Oct 14, 2017 at 10:55 PM, Jonathan Hull > > wrote:
>> 
>>> On Oct 14, 2017, at 7:55 PM, Xiaodi Wu via swift-evolution 
>>> > wrote:
>>> 
>>> > Ordered, yes, but it’s only admittedly poor wording that suggests 
>>> > multi-pass, and I don’t think anything there suggests finite.
>>> 
>>> If a Sequence is "guaranteed to iterate the same every time," then surely 
>>> it must be multi-pass; what's the alternative?
>> 
>> Single-pass, but where two dictionaries/sets with the same elements would be 
>> guaranteed to output the same ordering.
>> 
>> I'm not sure I understand. A single-pass sequence is one where iteration can 
>> happen only once because it is destructive. By definition, then, it is not 
>> guaranteed to "iterate the same" a second time. Neither sets nor 
>> dictionaries are single-pass sequences. Kevin says that his definition of a 
>> "Sequence" is something "guaranteed to iterate the same every time," which 
>> requires them to be multi-pass, does it not?
> 
> But if I am comparing two single-pass things, the order can still be defined 
> when they compare that one time.  Single-pass doesn’t mean that the order is 
> undefined.  On the contrary, as you point out, it has a “first” thing, and 
> then a thing after that, and so on.
> 
> Regardless, most of the objects we are talking about here are multi-pass 
> collections (e.g. sets).
> 
> Right, but I'm trying to figure out why Kevin wants a Sequence to "iterate 
> the same every time" and in what way that's not simply a Collection.

I guess you will have to ask Kevin that.


>>  That ordering can be arbitrary, but it shouldn’t leak internal 
>> representation such that the method used to create identical things affects 
>> the outcome of generic methods because of differences in internal 
>> representation.
>> 
>> 
>>>  It would be better to say that the iteration order is well-defined. That 
>>> will almost always mean documented, and usually predictable though 
>>> obviously e.g. RNGs and iterating in random order will not be predictable 
>>> by design.
>>> 
 That's actually more semantically constrained than what Swift calls a 
 `Collection` (which requires conforming types to be multi-pass and(?) 
 finite). By contrast, Swift's `SpongeBob` protocol explicitly permits 
 conforming single-pass, infinite, and/or unordered types. 
>>> 
>>> I think you’re talking about Sequence here, I’ve lost track of your 
>>> nonsense by now. Yes, the current Swift protocol named Sequence allows 
>>> unordered types. You seem to keep asserting that but not actually 
>>> addressing my argument, which is that allowing Sequences to be unordered 
>>> with the current API is undesired and actively harmful, and should 
>>> therefore be changed.
>>> 
>>> What is harmful about it?
>> 
>> After thinking about it, I think the harmful bit is that unordered sequences 
>> are leaking internal representation (In your example, this is causing people 
>> to be surprised when two sets with identical elements are generating 
>> different sequences/orderings based on how they were created).  You are 
>> correct when you say that this problem is even true for for-in.
>> 
>> I would not say it is a problem. Rather, by definition, iteration involves 
>> retrieving one element after another; if you're allowed to do that with Set, 
>> then the elements of a Set are observably ordered in some way. Since it's 
>> not an OrderedSet--i.e., order doesn't matter--then the only sensible 
>> conclusion is that the order of elements obtained in a for...in loop must be 
>> arbitrary. If you think this is harmful, then you must believe that one 
>> should be prohibited from iterating over an instance of Set. Otherwise, Set 
>> is inescapably a Sequence by the Swift definition of Sequence. All extension 
>> methods on Sequence like drop(while:) are really just conveniences for 
>> common things that you can do with iterated access; to my mind, they're 
>> essentially just alternative ways of spelling various for...in loops.
> 
> I think an argument could be made that you shouldn’t be able to iterate over 
> a set without first defining an ordering on it (even if that ordering is 
> somewhat arbitrary).  Maybe we have something like a “Sequenc(e)able” 
> protocol which defines things which can be turned into a sequence when 
> combined with some sort of ordering.  One possible ordering could be the 
> internal representation (At least in that case we are calling it out 
> specifically).  If I had to say 
> “setA.arbitraryOrder.elementsEqual(setB.arbitraryOrder)” I would definitely 
> be 

Re: [swift-evolution] [Draft] Rename Sequence.elementsEqual

2017-10-14 Thread Jonathan Hull via swift-evolution

> On Oct 14, 2017, at 9:21 PM, Xiaodi Wu  wrote:
> 
> On Sat, Oct 14, 2017 at 10:55 PM, Jonathan Hull  > wrote:
> 
>> On Oct 14, 2017, at 7:55 PM, Xiaodi Wu via swift-evolution 
>> > wrote:
>> 
>> > Ordered, yes, but it’s only admittedly poor wording that suggests 
>> > multi-pass, and I don’t think anything there suggests finite.
>> 
>> If a Sequence is "guaranteed to iterate the same every time," then surely it 
>> must be multi-pass; what's the alternative?
> 
> Single-pass, but where two dictionaries/sets with the same elements would be 
> guaranteed to output the same ordering.
> 
> I'm not sure I understand. A single-pass sequence is one where iteration can 
> happen only once because it is destructive. By definition, then, it is not 
> guaranteed to "iterate the same" a second time. Neither sets nor dictionaries 
> are single-pass sequences. Kevin says that his definition of a "Sequence" is 
> something "guaranteed to iterate the same every time," which requires them to 
> be multi-pass, does it not?

But if I am comparing two single-pass things, the order can still be defined 
when they compare that one time.  Single-pass doesn’t mean that the order is 
undefined.  On the contrary, as you point out, it has a “first” thing, and then 
a thing after that, and so on.

Regardless, most of the objects we are talking about here are multi-pass 
collections (e.g. sets).


>  
> That ordering can be arbitrary, but it shouldn’t leak internal representation 
> such that the method used to create identical things affects the outcome of 
> generic methods because of differences in internal representation.
> 
> 
>>  It would be better to say that the iteration order is well-defined. That 
>> will almost always mean documented, and usually predictable though obviously 
>> e.g. RNGs and iterating in random order will not be predictable by design.
>> 
>>> That's actually more semantically constrained than what Swift calls a 
>>> `Collection` (which requires conforming types to be multi-pass and(?) 
>>> finite). By contrast, Swift's `SpongeBob` protocol explicitly permits 
>>> conforming single-pass, infinite, and/or unordered types. 
>> 
>> I think you’re talking about Sequence here, I’ve lost track of your nonsense 
>> by now. Yes, the current Swift protocol named Sequence allows unordered 
>> types. You seem to keep asserting that but not actually addressing my 
>> argument, which is that allowing Sequences to be unordered with the current 
>> API is undesired and actively harmful, and should therefore be changed.
>> 
>> What is harmful about it?
> 
> After thinking about it, I think the harmful bit is that unordered sequences 
> are leaking internal representation (In your example, this is causing people 
> to be surprised when two sets with identical elements are generating 
> different sequences/orderings based on how they were created).  You are 
> correct when you say that this problem is even true for for-in.
> 
> I would not say it is a problem. Rather, by definition, iteration involves 
> retrieving one element after another; if you're allowed to do that with Set, 
> then the elements of a Set are observably ordered in some way. Since it's not 
> an OrderedSet--i.e., order doesn't matter--then the only sensible conclusion 
> is that the order of elements obtained in a for...in loop must be arbitrary. 
> If you think this is harmful, then you must believe that one should be 
> prohibited from iterating over an instance of Set. Otherwise, Set is 
> inescapably a Sequence by the Swift definition of Sequence. All extension 
> methods on Sequence like drop(while:) are really just conveniences for common 
> things that you can do with iterated access; to my mind, they're essentially 
> just alternative ways of spelling various for...in loops.

I think an argument could be made that you shouldn’t be able to iterate over a 
set without first defining an ordering on it (even if that ordering is somewhat 
arbitrary).  Maybe we have something like a “Sequenc(e)able” protocol which 
defines things which can be turned into a sequence when combined with some sort 
of ordering.  One possible ordering could be the internal representation (At 
least in that case we are calling it out specifically).  If I had to say 
“setA.arbitraryOrder.elementsEqual(setB.arbitraryOrder)” I would definitely be 
less surprised when it returns false even though setA == setB.

If that is unergonomic, we could define an arbitrary but consistent ordering 
over all Swift types that can be used to create a predictable sequence order 
for unordered types.  That is necessarily slower, but much safer… and people 
concerned with speed could use something like ‘arbitraryOrder’ above to regain 
full speed.

I am not arguing that that is necessarily the right approach, just that we need 
more thought/discussion around what is 

Re: [swift-evolution] [Draft] Rename Sequence.elementsEqual

2017-10-14 Thread Jonathan Hull via swift-evolution
Because the mathematical term you talk about has conditions which must be met 
to be used/valid.  Namely:

1) The “Alphabet” of elements must be totally ordered
2) The lexicographical comparison must be applied to ordered sequences of 
elements from that alphabet

Neither of those conditions are met for an unordered generic collection (e.g. a 
set of equatable, but not comparable elements).

The underlying issue here is that the “ordering” of the sequence coming out of 
a set/dictionary is undefined and may rely on internal implementation details.  
Building anything on top of that is problematic because the foundation is 
undefined.  Lexicographical’s connotation of applying a total order only 
compounds that original issue, especially if the elements are strings or some 
other sequential data type.

Thanks,
Jon

> On Oct 14, 2017, at 8:45 PM, Xiaodi Wu via swift-evolution 
>  wrote:
> 
> On Sat, Oct 14, 2017 at 8:11 PM, Michael Ilseman  > wrote:
> I think that “match” is a word to avoid for this, as this doesn’t have 
> anything to do with pattern matching, fuzzy matching, etc., while  “equals” 
> is precisely the concept we’re using.
> 
> What about the name “sequentiallyEquals”? Highlight the fact that we’re 
> talking about sequential ordering, i.e. whatever order the sequence provides, 
> as opposed to first doing some lexicographical ordering of elements 
> themselves.
> 
> var a: Set =  [3, 1, 2]
> a.sequentiallyEquals([1,2,3]) // result depends on application of equality in 
> a (potentially-arbitrary) sequential ordering
> 
> Whereas I could see the following being more confusing:
> 
> var a: Set =  [3, 1, 2]
> a.lexicographicallyEquals([1,2,3]) // result depends on application of 
> equality, but what meaning does “lexicographically” convey?
> 
> It’s not immediately clear to someone new to the API that “lexicographically” 
> speaks to the nature of the sequence’s (potentially-arbitrary) order, 
> irrespective of element. It could give the false impression that it speaks to 
> some nature of the elements themselves, in this case Ints, which have an 
> obvious lexicographical ordering. I don’t know how frequent that 
> misconception would be in practice, but it does cause me to do a double-take 
> in this contrived example.
> 
> 
> I'm entirely puzzled that apparently large numbers of people believe 
> lexicographical comparison, a term with a very specific mathematical 
> definition and no colloquial use, to mean what it does not. I'd like to avoid 
> inventing Swift-specific new terms for this particular concept which is not 
> at all unique to Swift. The other plausible terms I can see with some other 
> use might be "elementwise equals" or "entrywise equals" or "coordinatewise 
> equals."
>  
> 
>> On Oct 14, 2017, at 1:04 PM, Benjamin G via swift-evolution 
>> > wrote:
>> 
>> To answer more precisely this request (which remains valid no matter the 
>> protocol hierarchy). I propose
>> 
>> "matchesSequence" ( or simply "matches" or "match", whatever is more 
>> coherent with the naming guidelines).
>> 
>> So
>> var a: [Int] = [1,2,3]
>> a.matchesSequence([1,2,3]) returns true.
>> 
>> I first thought that the verb "matching" was too heavily associated to 
>> regular expressions, but i think that it's the correct equivalent for 
>> something as general as a sequence.
>> 
>> 
>> 
>> 
>> 
>> 
>> 
>> On Fri, Oct 13, 2017 at 1:24 AM, Xiaodi Wu via swift-evolution 
>> > wrote:
>> Rename Sequence.elementsEqual
>> 
>> Proposal: SE- 
>> Authors: Xiaodi Wu 
>> Review Manager: TBD
>> Status: Awaiting review
>>  
>> Introduction
>> 
>> The current behavior of Sequence.elementsEqual is potentially confusing to 
>> users given its name. Having surveyed the alternative solutions to this 
>> problem, it is proposed that the method be renamed to 
>> Sequence.lexicographicallyEquals.
>> 
>>  
>> Motivation
>> 
>> As outlined by Ole Begemann 
>> , use of 
>> Sequence.elementsEqual(_:) can lead to surprising results if the sequences 
>> compared are unordered:
>> 
>> var set1: Set = Set(1...5)
>> var set2: Set = Set((1...5).reversed())
>> 
>> set1 == set2 // true
>> set1.elementsEqual(set2) // false
>> This result does reflect the intended and documented behavior of the 
>> elementsEqual(_:) method, which performs a lexicographical elementwise 
>> comparison. That is, the method first compares set1.first to set2.first, 
>> then (if the two elements compare equal) compares the next element stored 
>> internally in set1 to the next 

Re: [swift-evolution] [Draft] Rename Sequence.elementsEqual

2017-10-14 Thread Jonathan Hull via swift-evolution

> On Oct 14, 2017, at 7:55 PM, Xiaodi Wu via swift-evolution 
>  wrote:
> 
> > Ordered, yes, but it’s only admittedly poor wording that suggests 
> > multi-pass, and I don’t think anything there suggests finite.
> 
> If a Sequence is "guaranteed to iterate the same every time," then surely it 
> must be multi-pass; what's the alternative?

Single-pass, but where two dictionaries/sets with the same elements would be 
guaranteed to output the same ordering. That ordering can be arbitrary, but it 
shouldn’t leak internal representation such that the method used to create 
identical things affects the outcome of generic methods because of differences 
in internal representation.


>  It would be better to say that the iteration order is well-defined. That 
> will almost always mean documented, and usually predictable though obviously 
> e.g. RNGs and iterating in random order will not be predictable by design.
> 
>> That's actually more semantically constrained than what Swift calls a 
>> `Collection` (which requires conforming types to be multi-pass and(?) 
>> finite). By contrast, Swift's `SpongeBob` protocol explicitly permits 
>> conforming single-pass, infinite, and/or unordered types. 
> 
> I think you’re talking about Sequence here, I’ve lost track of your nonsense 
> by now. Yes, the current Swift protocol named Sequence allows unordered 
> types. You seem to keep asserting that but not actually addressing my 
> argument, which is that allowing Sequences to be unordered with the current 
> API is undesired and actively harmful, and should therefore be changed.
> 
> What is harmful about it?

After thinking about it, I think the harmful bit is that unordered sequences 
are leaking internal representation (In your example, this is causing people to 
be surprised when two sets with identical elements are generating different 
sequences/orderings based on how they were created).  You are correct when you 
say that this problem is even true for for-in.

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


Re: [swift-evolution] [Draft] Rename Sequence.elementsEqual

2017-10-13 Thread Jonathan Hull via swift-evolution
It has been a while, but I believe a lexicographical ordering is basically a 
mapping from a set to the natural numbers (which should, in effect, provide a 
total ordering).  The mapping itself can be arbitrary, but the same set of 
things should never map to two different sequences (which just happens to be 
the example given).

This tells me that “lexicographicallyPrecedes” is actually misnamed unless it 
refers to something which has a defined totally ordering.

If we are looking to rename elementsEqual (which I would expect to check if the 
same elements are present regardless of ordering), I would recommend 
elementOrderingEqual or something like that that references that the answer 
will be affected by the internal representation/ordering of the sequence.

Thanks,
Jon

> On Oct 13, 2017, at 11:10 AM, Jarod Long via swift-evolution 
>  wrote:
> 
> The name that feels natural to me would be `sequentiallyEquals`. I don't 
> dispute that the term "lexicographical" is used correctly here, although at 
> least for me personally, it's not a word that I encounter frequently enough 
> to understand what this method would do without reading the documentation. 
> Like Kevin, if I were to guess what the method did without checking, I would 
> probably think that it compared lexicographically-sorted versions of the 
> collections.
> 
> But the consistency with `lexicographicallyPrecedes` is a pretty strong 
> argument, although `sequentiallyPrecedes` would also feel more natural to me 
> there, and my suspicion about the mentioned lack of evidence that the method 
> has been a pitfall for users is that it's not actually used often enough out 
> in the wild to have heard much about it. That's just a guess though. This 
> proposal is the first time I've learned of its existence.
> 
> In any case, my ideal version of this proposal would use `sequentiallyEquals` 
> and also rename `lexicographicallyPrecedes` to `sequentiallyPrecedes`, but I 
> still like the proposal overall as-is. Thanks for bringing it forward!
> 
> Jarod
> 
> On Oct 12, 2017, 16:24 -0700, Xiaodi Wu via swift-evolution 
> , wrote:
>> Rename Sequence.elementsEqual
>> 
>> Proposal: SE- 
>> Authors: Xiaodi Wu 
>> Review Manager: TBD
>> Status: Awaiting review
>>  
>> Introduction
>> 
>> The current behavior of Sequence.elementsEqual is potentially confusing to 
>> users given its name. Having surveyed the alternative solutions to this 
>> problem, it is proposed that the method be renamed to 
>> Sequence.lexicographicallyEquals.
>> 
>>  
>> Motivation
>> 
>> As outlined by Ole Begemann 
>> , use of 
>> Sequence.elementsEqual(_:) can lead to surprising results if the sequences 
>> compared are unordered:
>> 
>> var set1: Set = Set(1...5)
>> var set2: Set = Set((1...5).reversed())
>> 
>> set1 == set2 // true
>> set1.elementsEqual(set2) // false
>> This result does reflect the intended and documented behavior of the 
>> elementsEqual(_:) method, which performs a lexicographical elementwise 
>> comparison. That is, the method first compares set1.first to set2.first, 
>> then (if the two elements compare equal) compares the next element stored 
>> internally in set1 to the next element stored internally in set2, and so on.
>> 
>> In almost all circumstances where a set is compared to another set, or a 
>> dictionary is compared to another dictionary, users should use == instead of 
>> elementsEqual(_:).
>> 
>>  
>> Proposed
>>  solution
>> 
>> The proposed solution is the result of an iterative process of reasoning, 
>> presented here:
>> 
>> The first and most obvious solution is to remove the elementsEqual(_:) 
>> method altogether in favor of ==. This prevents its misuse. However, because 
>> elementsEqual(_:) is a generic method on Sequence, we can use it to compare 
>> an instance of UnsafeBufferPointer to an instance of [Int]. This is a 
>> useful and non-redundant feature which would be eliminated if the method is 
>> removed altogether.
>> 
>> A second solution  is to create 
>> overloads that forbid the use of the elementsEqual(_:) method specifically 
>> in non-generic code. This would prevent misuse in non-generic code; however, 
>> it would also forbid legitimate mixed-type comparisons in non-generic code 
>> while failing to prevent misuse in generic code. The solution also creates a 
>> difference in the behavior of generic and non-generic code calling the same 
>> method, which is potentially confusing, without solving the problem 
>> completely.
>> 
>> A third solution is to 

Re: [swift-evolution] [Draft] Rename Sequence.elementsEqual

2017-10-13 Thread Jonathan Hull via swift-evolution
I would also expect lexicographicallyEquals to sort the elements (or otherwise 
create/reference a total ordering) before checking for equality.  I would be 
more surprised by the behavior of a function named this than elementsEqual.

Given the name, I would expect elementsEqual to return true if two sequences 
have the same elements, regardless of ordering (this would be a valuable 
function IMHO).  I would expect lexicographicallyEquals to compare the elements 
in some lexicographical order defined for the type which overrides the internal 
ordering of the sequence.

Kevin is right… the real answer is that the actual intended function really 
shouldn’t exist on unordered sequences.

Thanks,
Jon

> On Oct 13, 2017, at 10:12 AM, Kevin Nattinger via swift-evolution 
>  wrote:
> 
>> 
>> On Oct 13, 2017, at 10:01 AM, Michael Ilseman > > wrote:
>> 
>> 
>> 
>>> On Oct 12, 2017, at 9:57 PM, Kevin Nattinger via swift-evolution 
>>> > wrote:
>>> 
>>> –∞
>>> 
>>> 1. I strongly object to the proposed name. It doesn't make it more clear to 
>>> me what the method does, and is misleading at best. Among other issues, 
>>> "lexicographical" is defined as alphabet order, and (1) this method applies 
>>> to objects that are not Strings, and (2) this method's behavior isn't any 
>>> more well-defined for Strings, so that name is even more of a lie than the 
>>> original.
>>> 
>> 
>> FWIW, in the context of String, "lexicographical ordering” does not imply 
>> human-written-language-alphabetical order at all, as there’s no universal 
>> alphabetical ordering for human language. I.e., such a concrete notion for 
>> Strings does not exist, not even theoretically. “Lexicographical” derives 
>> its meaning from the mathematical usage[1] which uses that term as well as 
>> “alphabet” without being restricted to human-written-language, in which it 
>> means some total ordering over a finite set.
>> 
>> [1] https://en.wikipedia.org/wiki/Lexicographical_order 
>> 
> I see, apologies for the mistake. 
> Regardless of the specific type of ordering, lexicographicallyEquals says to 
> me that the objects should be sorted into lexicographical order and compared. 
> Precisely the opposite of the proposal.
> 
>> 
>>> 2. This is really just a symptom of a bigger problem. The fact that two 
>>> Sets can compare equal and yet return different results for that method 
>>> (among too many others) is logically inconsistent and points to a much 
>>> deeper issue with Set and Sequence. It is probably about 3 releases too 
>>> late to get this straightened out properly, but I'll outline the real issue 
>>> in case someone has an idea for fixing it.
>>> 
>>> The root of the problem is that Set conforms to Sequence, but Sequence 
>>> doesn't require a well-defined order. Since Set doesn't have a well-defined 
>>> order, a significant portion of its interface is unspecified. The methods 
>>> are implemented because they have to be, but they doesn't have well-defined 
>>> or necessarily consistent results.
>>> 
>>> A sequence is, by definition, ordered. That is reflected in the fact that 
>>> over half the methods in the main Sequence definition* make no sense and 
>>> are not well-defined unless there is a well-defined order to the sequence 
>>> itself. What does it even mean to `dropFirst()` in a Set? The fact that two 
>>> objects that compare equal can give different results for a 100% 
>>> deterministic function is illogical, nonsensical, and dangerous.
>>> 
>>> * 7/12 by my count, ignoring `_*` funcs but including the `var`
>>> 
>>> The current contents of Sequence can be cleanly divided into two groups; 
>>> those that return SubSequence imply a specific ordering, and the rest do 
>>> not.
>>> 
>>>  I think those should be/should have been two separate protocols:
>>> 
>>> public protocol Iterable {
>>>   associatedtype Iterator: IteratorProtocol
>>>   func map(...) -> [T] // Iterable where .Iterator.Element == T
>>>   func filter(...) -> [Iterator.Element] // Iterable where 
>>> .Iterator.Element == Self.Iterator.Element
>>>   func forEach(...)
>>>   func makeIterator() -> Iterator
>>>   var underestimatedCount: Int { get }
>>> }
>>> 
>>> public protocol Sequence: Iterable { // Maybe OrderedSequence just to make 
>>> the well-defined-order requirement explicit
>>>   associatedtype SubSequence
>>>   func dropFirst(...)   -> SubSequence   // Sequence where 
>>> .Iterator.Element == Self.Iterator.Element
>>>   func dropLast(...)-> SubSequence   //" "
>>>   func drop(while...)   -> SubSequence   //" "
>>>   func prefix(...)  -> SubSequence   //" "
>>>   func prefix(while...) -> SubSequence   //" "
>>>   func suffix(...)  -> SubSequence   //" "
>>>   func split(...where...)  -> [SubSequence] // Iterable where 
>>> 

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

2017-10-13 Thread Jonathan Hull via swift-evolution
I like the earlier version we were talking about with both .random(in: 
ClosedRange<>) and .random(in:ClosedRange<>, using: RandomSource)

Thanks,
Jon

> On Oct 12, 2017, at 10:30 PM, Brent Royal-Gordon via swift-evolution 
>  wrote:
> 
> On Oct 11, 2017, at 10:02 AM, Kevin Nattinger via swift-evolution 
>  wrote:
>> 
>> IMO, if we have the extensions on Int(eger)/Float(ingPoint)/Array 
>> (RandomAccessSequence?), they should just be for convenience and with a sane 
>> default RNG*, and users that need more should just use methods on the RNGs 
>> directly.
> 
> No—that means code which uses these extremely convenient and attractive APIs 
> can never be testable and that there's no obvious way to go from "use the 
> default RNG" to "use this specific RNG".
> 
> Methods which use an RNG should take that RNG as a parameter—a parameter with 
> a default value of "the default RNG":
> 
>   init(randomIn range: CountableRange, from randomizer: Randomizer 
> = DefaultRandomizer.shared) {
>   …
>   }
> 
> This properly separates concerns between the Randomizer (which knows how to 
> return random data) and the type (which knows how to construct itself from 
> random data). It also makes it easy to use a randomized API you already knew 
> about with a RandomSource, and it creates a convention that users can apply 
> to their own designs for how to write testable and customizable randomized 
> code. We might even add a local refactoring which automatically adds a 
> Randomizer parameter to the function and passes it to randomized calls within 
> the body.
> 
> Don't add a global setter—you don't know what it might affect. Don't add a 
> bunch of calls constructing arbitrary types to the Randomizer (or whatever 
> it's called) protocol. Do it with dependency injection: pass the Randomizer 
> as a parameter.
> 
> -- 
> Brent Royal-Gordon
> Sent from my iPhone
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

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


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

2017-10-04 Thread Jonathan Hull via swift-evolution
What about the opposite then, where we internally switch to a slightly less 
random source, but keep the extra function so conscientious programmers can 
check/handle cases where there isn’t enough entropy specially if needed?

Thanks,
Jon


> On Oct 4, 2017, at 2:55 AM, Xiaodi Wu  wrote:
> 
> Seems like the API would be actively hiding he possibility of failure so that 
> you’d have to be in the know to prevent it. Those who don’t know about it 
> would be hunting down a ghost as they’re trying to debug, especially if their 
> program crashes rarely, stochastically, and non-reproducibly because a third 
> party library calls random() in code they can’t see. I think this makes 
> trapping the least acceptable of all options.
> On Wed, Oct 4, 2017 at 04:49 Jonathan Hull  > wrote:
> @Xiaodi:  What do you think of the possibility of trapping in cases of low 
> entropy, and adding an additional global function that checks for entropy so 
> that conscientious programmers can avoid the trap and provide an alternative 
> (or error message)?
> 
> Thanks,
> Jon
> 
> 
>> On Oct 4, 2017, at 2:41 AM, Xiaodi Wu > > wrote:
>> 
>> 
>> On Wed, Oct 4, 2017 at 02:39 Félix Cloutier > > wrote:
>> I'm really not enthusiastic about `random() -> Self?` or `random() throws -> 
>> Self` when the only possible error is that some global object hasn't been 
>> initialized.
>> 
>> The idea of having `random` straight on integers and floats and collections 
>> was to provide a simple interface, but using a global CSPRNG for those 
>> operations comes at a significant usability cost. I think that something has 
>> to go:
>> 
>> Drop the random methods on FixedWidthInteger, FloatingPoint
>> ...or drop the CSPRNG as a default
>> Drop the optional/throws, and trap on error
>> 
>> I know I wouldn't use the `Int.random()` method if I had to unwrap every 
>> single result, when getting one non-nil result guarantees that the program 
>> won't see any other nil result again until it restarts.
>> 
>> From the perspective of an app that can be suspended and resumed at any 
>> time, “until it restarts” could be as soon as the next invocation of 
>> `Int.random()`, could it not?
>> 
>> 
>> Félix
>> 
>>> Le 3 oct. 2017 à 23:44, Jonathan Hull >> > a écrit :
>>> 
>>> I like the idea of splitting it into 2 separate “Random” proposals.
>>> 
>>> The first would have Xiaodi’s built-in CSPRNG which only has the interface:
>>> 
>>> On FixedWidthInteger:
>>> static func random()throws -> Self
>>> static func random(in range: ClosedRange)throws -> Self
>>> 
>>> On Double:
>>> static func random()throws -> Double
>>> static func random(in range: ClosedRange)throws -> Double
>>> 
>>> (Everything else we want, like shuffled(), could be built in later 
>>> proposals by calling those functions)
>>> 
>>> The other option would be to remove the ‘throws’ from the above functions 
>>> (perhaps fatalError-ing), and provide an additional function which can be 
>>> used to check that there is enough entropy (so as to avoid the crash or 
>>> fall back to a worse source when the CSPRNG is unavailable).
>>> 
>>> 
>>> 
>>> Then a second proposal would bring in the concept of RandomSources 
>>> (whatever we call them), which can return however many random bytes you ask 
>>> for… and a protocol for types which know how to initialize themselves from 
>>> those bytes.  That might be spelled like 'static func random(using: 
>>> RandomSource)->Self'.  As a convenience, the source would also be able to 
>>> create FixedWidthIntegers and Doubles (both with and without a range), and 
>>> would also have the coinFlip() and oneIn(UInt)->Bool functions. Most types 
>>> should be able to build themselves off of that.  There would be a default 
>>> source which is built from the first protocol.
>>> 
>>> I also really think we should have a concept of Repeatably-Random as a 
>>> subprotocol for the second proposal.  I see far too many shipping apps 
>>> which have bugs due to using arc4Random when they really needed a 
>>> repeatable source (e.g. patterns and lines jump around when you resize 
>>> things). If it was an easy option, people would use it when appropriate. 
>>> This would just mean a sub-protocol which has an initializer which takes a 
>>> seed, and the ability to save/restore state (similar to CGContexts).
>>> 
>>> The second proposal would also include things like shuffled() and 
>>> shuffled(using:).
>>> 
>>> Thanks,
>>> Jon
>>> 
>>> 
>>> 
 On Oct 3, 2017, at 9:31 PM, Alejandro Alonso > wrote:
 
 I really like the schedule here. After reading for a while, I do agree 
 with Brent that stdlib should very primitive in functionality that it 
 provides. I also agree that 

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

2017-10-04 Thread Jonathan Hull via swift-evolution
@Xiaodi:  What do you think of the possibility of trapping in cases of low 
entropy, and adding an additional global function that checks for entropy so 
that conscientious programmers can avoid the trap and provide an alternative 
(or error message)?

Thanks,
Jon

> On Oct 4, 2017, at 2:41 AM, Xiaodi Wu  wrote:
> 
> 
> On Wed, Oct 4, 2017 at 02:39 Félix Cloutier  > wrote:
> I'm really not enthusiastic about `random() -> Self?` or `random() throws -> 
> Self` when the only possible error is that some global object hasn't been 
> initialized.
> 
> The idea of having `random` straight on integers and floats and collections 
> was to provide a simple interface, but using a global CSPRNG for those 
> operations comes at a significant usability cost. I think that something has 
> to go:
> 
> Drop the random methods on FixedWidthInteger, FloatingPoint
> ...or drop the CSPRNG as a default
> Drop the optional/throws, and trap on error
> 
> I know I wouldn't use the `Int.random()` method if I had to unwrap every 
> single result, when getting one non-nil result guarantees that the program 
> won't see any other nil result again until it restarts.
> 
> From the perspective of an app that can be suspended and resumed at any time, 
> “until it restarts” could be as soon as the next invocation of 
> `Int.random()`, could it not?
> 
> 
> Félix
> 
>> Le 3 oct. 2017 à 23:44, Jonathan Hull > > a écrit :
>> 
>> I like the idea of splitting it into 2 separate “Random” proposals.
>> 
>> The first would have Xiaodi’s built-in CSPRNG which only has the interface:
>> 
>> On FixedWidthInteger:
>>  static func random()throws -> Self
>>  static func random(in range: ClosedRange)throws -> Self
>> 
>> On Double:
>>  static func random()throws -> Double
>>  static func random(in range: ClosedRange)throws -> Double
>> 
>> (Everything else we want, like shuffled(), could be built in later proposals 
>> by calling those functions)
>> 
>> The other option would be to remove the ‘throws’ from the above functions 
>> (perhaps fatalError-ing), and provide an additional function which can be 
>> used to check that there is enough entropy (so as to avoid the crash or fall 
>> back to a worse source when the CSPRNG is unavailable).
>> 
>> 
>> 
>> Then a second proposal would bring in the concept of RandomSources (whatever 
>> we call them), which can return however many random bytes you ask for… and a 
>> protocol for types which know how to initialize themselves from those bytes. 
>>  That might be spelled like 'static func random(using: RandomSource)->Self'. 
>>  As a convenience, the source would also be able to create 
>> FixedWidthIntegers and Doubles (both with and without a range), and would 
>> also have the coinFlip() and oneIn(UInt)->Bool functions. Most types should 
>> be able to build themselves off of that.  There would be a default source 
>> which is built from the first protocol.
>> 
>> I also really think we should have a concept of Repeatably-Random as a 
>> subprotocol for the second proposal.  I see far too many shipping apps which 
>> have bugs due to using arc4Random when they really needed a repeatable 
>> source (e.g. patterns and lines jump around when you resize things). If it 
>> was an easy option, people would use it when appropriate. This would just 
>> mean a sub-protocol which has an initializer which takes a seed, and the 
>> ability to save/restore state (similar to CGContexts).
>> 
>> The second proposal would also include things like shuffled() and 
>> shuffled(using:).
>> 
>> Thanks,
>> Jon
>> 
>> 
>> 
>>> On Oct 3, 2017, at 9:31 PM, Alejandro Alonso >> > wrote:
>>> 
>>> I really like the schedule here. After reading for a while, I do agree with 
>>> Brent that stdlib should very primitive in functionality that it provides. 
>>> I also agree that the most important part right now is designing the 
>>> internal crypto on which the numeric types use to return their respected 
>>> random number. On the discussion of how we should handle not enough entropy 
>>> with the device random, from a users perspective it makes sense that 
>>> calling .random should just give me a random number, but from a developers 
>>> perspective I see Optional being the best choice here. While I think 
>>> blocking could, in most cases, provide the user an easier API, we have to 
>>> do this right and be safe here by providing a value that indicates that 
>>> there is room for error here. As for the generator abstraction, I believe 
>>> there should be a bare basic protocol that sets a layout for new generators 
>>> and should be focusing on its requirements. 
>>> 
>>> Whether or not RandomAccessCollection and MutableCollection should get 
>>> .random and .shuffle/.shuffled in this first proposal is completely up in 
>>> the air for me. It 

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

2017-10-04 Thread Jonathan Hull via swift-evolution
I like the idea of splitting it into 2 separate “Random” proposals.

The first would have Xiaodi’s built-in CSPRNG which only has the interface:

On FixedWidthInteger:
static func random()throws -> Self
static func random(in range: ClosedRange)throws -> Self

On Double:
static func random()throws -> Double
static func random(in range: ClosedRange)throws -> Double

(Everything else we want, like shuffled(), could be built in later proposals by 
calling those functions)

The other option would be to remove the ‘throws’ from the above functions 
(perhaps fatalError-ing), and provide an additional function which can be used 
to check that there is enough entropy (so as to avoid the crash or fall back to 
a worse source when the CSPRNG is unavailable).



Then a second proposal would bring in the concept of RandomSources (whatever we 
call them), which can return however many random bytes you ask for… and a 
protocol for types which know how to initialize themselves from those bytes.  
That might be spelled like 'static func random(using: RandomSource)->Self'.  As 
a convenience, the source would also be able to create FixedWidthIntegers and 
Doubles (both with and without a range), and would also have the coinFlip() and 
oneIn(UInt)->Bool functions. Most types should be able to build themselves off 
of that.  There would be a default source which is built from the first 
protocol.

I also really think we should have a concept of Repeatably-Random as a 
subprotocol for the second proposal.  I see far too many shipping apps which 
have bugs due to using arc4Random when they really needed a repeatable source 
(e.g. patterns and lines jump around when you resize things). If it was an easy 
option, people would use it when appropriate. This would just mean a 
sub-protocol which has an initializer which takes a seed, and the ability to 
save/restore state (similar to CGContexts).

The second proposal would also include things like shuffled() and 
shuffled(using:).

Thanks,
Jon



> On Oct 3, 2017, at 9:31 PM, Alejandro Alonso  wrote:
> 
> I really like the schedule here. After reading for a while, I do agree with 
> Brent that stdlib should very primitive in functionality that it provides. I 
> also agree that the most important part right now is designing the internal 
> crypto on which the numeric types use to return their respected random 
> number. On the discussion of how we should handle not enough entropy with the 
> device random, from a users perspective it makes sense that calling .random 
> should just give me a random number, but from a developers perspective I see 
> Optional being the best choice here. While I think blocking could, in most 
> cases, provide the user an easier API, we have to do this right and be safe 
> here by providing a value that indicates that there is room for error here. 
> As for the generator abstraction, I believe there should be a bare basic 
> protocol that sets a layout for new generators and should be focusing on its 
> requirements. 
> 
> Whether or not RandomAccessCollection and MutableCollection should get 
> .random and .shuffle/.shuffled in this first proposal is completely up in the 
> air for me. It makes sense, to me, to include the .random in this proposal 
> and open another one .shuffle/.shuffled, but I can see arguments that should 
> say we create something separate for these two, or include all of it in this 
> proposal.
> 
> - Alejandro
> 
> On Sep 27, 2017, 7:29 PM -0500, Xiaodi Wu , wrote:
>> 
>> On Wed, Sep 27, 2017 at 00:18 Félix Cloutier > > wrote:
>>> Le 26 sept. 2017 à 16:14, Xiaodi Wu >> > a écrit :
>>> 
>> 
>>> On Tue, Sep 26, 2017 at 11:26 AM, Félix Cloutier >> > wrote:
>>> 
>>> It's possible to use a CSPRNG-grade algorithm and seed it once to get a 
>>> reproducible sequence, but when you use it as a CSPRNG, you typically feed 
>>> entropy back into it at nondeterministic points to ensure that even if you 
>>> started with a bad seed, you'll eventually get to an alright state. Unless 
>>> you keep track of when entropy was mixed in and what the values were, 
>>> you'll never get a reproducible CSPRNG.
>>> 
>>> We would give developers a false sense of security if we provided them with 
>>> CSPRNG-grade algorithms that we called CSPRNGs and that they could seed 
>>> themselves. Just because it says "crypto-secure" in the name doesn't mean 
>>> that it'll be crypto-secure if it's seeded with time(). Therefore, 
>>> "reproducible" vs "non-reproducible" looks like a good distinction to me.
>>> 
>>> I disagree here, in two respects:
>>> 
>>> First, whether or not a particular PRNG is cryptographically secure is an 
>>> intrinsic property of the algorithm; whether it's "reproducible" or not is 
>>> 

[swift-evolution] Get a list of Concrete Implementers for Protocols

2017-10-03 Thread Jonathan Hull via swift-evolution
Hi Evolution,

We talked a while back about being able to get a list of all concrete 
implementations for a protocol (i.e. all the types that adhere to it).  Is this 
still being planned?

There are a couple of big use-cases for this:

• The first is for plug-ins and other things that require registration. A 
protocol can provide a way for them to be auto-registered by calling a static 
method from the protocol on each of them.

• The second is that you can build robust + extensible factories. 


I definitely have use for this right now.  I am currently writing a UI 
generator that auto-generates functioning UI based on a given set of 
criteria/data.  Right now, I have to manually register each partial-template 
(of which there will eventually be several thousand) with the factory by hand, 
which is an error-prone process. It is one of those things that was doable in 
ObjC pretty easily, but I still haven’t figured out how to do it in Swift.

Thanks,
Jon

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


Re: [swift-evolution] A path forward on rationalizing unicode identifiers and operators

2017-10-01 Thread Jonathan Hull via swift-evolution
Understood.

Thanks,
Jon

> On Oct 1, 2017, at 4:20 PM, Chris Lattner  wrote:
> 
> Something like that is possible, but makes the language/compiler more 
> complicated by introducing a whole new concept to the source distribution.  
> It also doesn’t address the cases where you want to do a parse but don’t have 
> the dependent source files, e.g. in a source browser tool like ViewVC.
> 
> -Chris
> 
>> On Oct 1, 2017, at 4:17 PM, Jonathan Hull  wrote:
>> 
>> Gotcha.  What if the definitions were in a special file similar to the 
>> info.plist that was read before other parsing, with one file per package?
>> 
>> Thanks,
>> Jon
>> 
>> 
>>> On Oct 1, 2017, at 4:09 PM, Chris Lattner  wrote:
>>> 
>>> On Sep 30, 2017, at 7:10 PM, Jonathan Hull  wrote:
 I have a technical question on this:
 
 Instead of parsing these into identifiers & operators, would it be 
 possible to parse these into 3 categories: Identifiers, Operators, and 
 Ambiguous?
 
 The ambiguous category would be disallowed for the moment, as you say.  
 But since they are rarely used, maybe we can allow a declaration (similar 
 to how we define operators) that effectively pulls it into one of the 
 other categories (not in terms of tokenization, but in terms of how it can 
 be used in Swift).  
>>> 
>>> This is commonly requested, but the third category isn’t practical.  
>>> 
>>> Swift statically partitions characters between identifiers and operators to 
>>> make it possible to parse a Swift source file without parsing all of its 
>>> dependencies.  If you could have directives that change this, it would be 
>>> difficult or perhaps impossible to parse a file that used these characters 
>>> without parsing/reading the transitive closure of dependent modules.
>>> 
>>> This is important for compile speed and some tooling, and is an area that C 
>>> gets wrong - its grammar requires all headers to be parsed in order to 
>>> distinguish between type names and normal identifiers.
>>> 
>>> -Chris
>>> 
>>> 
>> 
> 
> 

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


Re: [swift-evolution] A path forward on rationalizing unicode identifiers and operators

2017-10-01 Thread Jonathan Hull via swift-evolution
Gotcha.  What if the definitions were in a special file similar to the 
info.plist that was read before other parsing, with one file per package?

Thanks,
Jon


> On Oct 1, 2017, at 4:09 PM, Chris Lattner  wrote:
> 
> On Sep 30, 2017, at 7:10 PM, Jonathan Hull  wrote:
>> I have a technical question on this:
>> 
>> Instead of parsing these into identifiers & operators, would it be possible 
>> to parse these into 3 categories: Identifiers, Operators, and Ambiguous?
>> 
>> The ambiguous category would be disallowed for the moment, as you say.  But 
>> since they are rarely used, maybe we can allow a declaration (similar to how 
>> we define operators) that effectively pulls it into one of the other 
>> categories (not in terms of tokenization, but in terms of how it can be used 
>> in Swift).  
> 
> This is commonly requested, but the third category isn’t practical.  
> 
> Swift statically partitions characters between identifiers and operators to 
> make it possible to parse a Swift source file without parsing all of its 
> dependencies.  If you could have directives that change this, it would be 
> difficult or perhaps impossible to parse a file that used these characters 
> without parsing/reading the transitive closure of dependent modules.
> 
> This is important for compile speed and some tooling, and is an area that C 
> gets wrong - its grammar requires all headers to be parsed in order to 
> distinguish between type names and normal identifiers.
> 
> -Chris
> 
> 

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


Re: [swift-evolution] A path forward on rationalizing unicode identifiers and operators

2017-09-30 Thread Jonathan Hull via swift-evolution
It won’t compile.

> On Sep 30, 2017, at 7:14 PM, Taylor Swift <kelvin1...@gmail.com> wrote:
> 
> what happens if two public operator declarations conflict?
> 
> On Sat, Sep 30, 2017 at 9:10 PM, Jonathan Hull via swift-evolution 
> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
> I have a technical question on this:
> 
> Instead of parsing these into identifiers & operators, would it be possible 
> to parse these into 3 categories: Identifiers, Operators, and Ambiguous?
> 
> The ambiguous category would be disallowed for the moment, as you say.  But 
> since they are rarely used, maybe we can allow a declaration (similar to how 
> we define operators) that effectively pulls it into one of the other 
> categories (not in terms of tokenization, but in terms of how it can be used 
> in Swift).  Trying to pull it into both would be a compilation error.
> 
> That way, Xiaodi can have a framework which lets her use superscript T as an 
> identifier, and I can have one where I use superscript 2 to square things.  
> The obvious/frequently used characters would not be ambiguous, so it would 
> only slow down compilation when the rare/ambiguous characters are used.
> 
> In my mind, this would be the ideal solution, and it could be done in stages 
> (with the ambiguous characters just being forbidden for now), but I am not 
> sure if it is technically possible.
> 
> Thanks,
> Jon
> 
>> On Sep 30, 2017, at 3:59 PM, Chris Lattner via swift-evolution 
>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>> 
>> 
>> The core team recently met to discuss PR609 - Refining identifier and 
>> operator symbology:
>> https://github.com/xwu/swift-evolution/blob/7c2c4df63b1d92a1677461f41bc638f31926c9c3/proposals/-refining-identifier-and-operator-symbology.md
>>  
>> <https://github.com/xwu/swift-evolution/blob/7c2c4df63b1d92a1677461f41bc638f31926c9c3/proposals/-refining-identifier-and-operator-symbology.md>
>> 
>> The proposal correctly observes that the partitioning of unicode codepoints 
>> into identifiers and operators is a mess in some cases.  It really is an 
>> outright bug for  to be an identifier, but ☹️ to be an operator.  That 
>> said, the proposal itself is complicated and is defined in terms of a bunch 
>> of unicode classes that may evolve in the “wrong way for Swift” in the 
>> future.
>> 
>> The core team would really like to get this sorted out for Swift 5, and 
>> sooner is better than later :-).  Because it seems that this is a really 
>> hard problem and that perfection is becoming the enemy of good 
>> <https://en.wikipedia.org/wiki/Perfect_is_the_enemy_of_good>, the core team 
>> requests the creation of a new proposal with a different approach.  The 
>> general observation is that there are three kinds of characters: things that 
>> are obviously identifiers, things that are obviously math operators, and 
>> things that are non-obvious.  Things that are non-obvious can be made into 
>> invalid code points, and legislated later in follow-up proposals if/when 
>> someone cares to argue for them.
>> 
>> 
>> To make progress on this, we suggest a few separable steps:
>> 
>> First, please split out the changes to the ASCII characters (e.g. . and \ 
>> operator parsing rules) to its own (small) proposal, since it is unrelated 
>> to the unicode changes, and can make progress on that proposal independently.
>> 
>> 
>> Second, someone should take a look at the concrete set of unicode 
>> identifiers that are accepted by Swift 4 and write a new proposal that 
>> splits them into the three groups: those that are clearly identifiers (which 
>> become identifiers), those that are clearly operators (which become 
>> operators), and those that are unclear or don’t matter (these become invalid 
>> code points).
>> 
>> I suggest that the criteria be based on utility for Swift code, not on the 
>> underlying unicode classification.  For example, the discussion thread for 
>> PR609 mentions that the T character in “  xᵀ  ” is defined in unicode as a 
>> latin “letter”.  Despite that, its use is Swift would clearly be as a 
>> postfix operator, so we should classify it as an operator.
>> 
>> Other suggestions:
>>  - Math symbols are operators excepting those primarily used as identifiers 
>> like “alpha”.  If there are any characters that are used for both, this 
>> proposal should make them invalid.
>>  - While there may be useful ranges for some identifiers (e.g. to handle 
>> european accented characters), th

Re: [swift-evolution] A path forward on rationalizing unicode identifiers and operators

2017-09-30 Thread Jonathan Hull via swift-evolution
I have a technical question on this:

Instead of parsing these into identifiers & operators, would it be possible to 
parse these into 3 categories: Identifiers, Operators, and Ambiguous?

The ambiguous category would be disallowed for the moment, as you say.  But 
since they are rarely used, maybe we can allow a declaration (similar to how we 
define operators) that effectively pulls it into one of the other categories 
(not in terms of tokenization, but in terms of how it can be used in Swift).  
Trying to pull it into both would be a compilation error.

That way, Xiaodi can have a framework which lets her use superscript T as an 
identifier, and I can have one where I use superscript 2 to square things.  The 
obvious/frequently used characters would not be ambiguous, so it would only 
slow down compilation when the rare/ambiguous characters are used.

In my mind, this would be the ideal solution, and it could be done in stages 
(with the ambiguous characters just being forbidden for now), but I am not sure 
if it is technically possible.

Thanks,
Jon

> On Sep 30, 2017, at 3:59 PM, Chris Lattner via swift-evolution 
>  wrote:
> 
> 
> The core team recently met to discuss PR609 - Refining identifier and 
> operator symbology:
> https://github.com/xwu/swift-evolution/blob/7c2c4df63b1d92a1677461f41bc638f31926c9c3/proposals/-refining-identifier-and-operator-symbology.md
>  
> 
> 
> The proposal correctly observes that the partitioning of unicode codepoints 
> into identifiers and operators is a mess in some cases.  It really is an 
> outright bug for  to be an identifier, but ☹️ to be an operator.  That said, 
> the proposal itself is complicated and is defined in terms of a bunch of 
> unicode classes that may evolve in the “wrong way for Swift” in the future.
> 
> The core team would really like to get this sorted out for Swift 5, and 
> sooner is better than later :-).  Because it seems that this is a really hard 
> problem and that perfection is becoming the enemy of good 
> , the core team 
> requests the creation of a new proposal with a different approach.  The 
> general observation is that there are three kinds of characters: things that 
> are obviously identifiers, things that are obviously math operators, and 
> things that are non-obvious.  Things that are non-obvious can be made into 
> invalid code points, and legislated later in follow-up proposals if/when 
> someone cares to argue for them.
> 
> 
> To make progress on this, we suggest a few separable steps:
> 
> First, please split out the changes to the ASCII characters (e.g. . and \ 
> operator parsing rules) to its own (small) proposal, since it is unrelated to 
> the unicode changes, and can make progress on that proposal independently.
> 
> 
> Second, someone should take a look at the concrete set of unicode identifiers 
> that are accepted by Swift 4 and write a new proposal that splits them into 
> the three groups: those that are clearly identifiers (which become 
> identifiers), those that are clearly operators (which become operators), and 
> those that are unclear or don’t matter (these become invalid code points).
> 
> I suggest that the criteria be based on utility for Swift code, not on the 
> underlying unicode classification.  For example, the discussion thread for 
> PR609 mentions that the T character in “  xᵀ  ” is defined in unicode as a 
> latin “letter”.  Despite that, its use is Swift would clearly be as a postfix 
> operator, so we should classify it as an operator.
> 
> Other suggestions:
>  - Math symbols are operators excepting those primarily used as identifiers 
> like “alpha”.  If there are any characters that are used for both, this 
> proposal should make them invalid.
>  - While there may be useful ranges for some identifiers (e.g. to handle 
> european accented characters), the Emoji range should probably have each 
> codepoint independently judged, and currently unassigned codepoints should 
> not get a meaning defined for them.
>  - Unicode “faces”, “people”, “animals” etc are all identifiers.
>  - In order to reduce the scope of the proposal, it is a safe default to 
> exclude characters that are unlikely to be used by Swift code today, 
> including Braille, weird currency symbols, or any set of characters that are 
> so broken and useless in Swift 4 that it isn’t worth worrying about.
>  - The proposal is likely to turn a large number of code points into rejected 
> characters.  In the discussions, some people will be tempted to argue 
> endlessly about individual rejections.  To control that, we can require that 
> people point out an example where the character is already in use, or where 
> it has a clear application to a domain that is known today: the discussion 

Re: [swift-evolution] Idea: Public Access Modifier Respected in Type Definition

2017-09-28 Thread Jonathan Hull via swift-evolution
I should also mention that this is from a class of error where it becomes more 
likely with expertise.  Thus, the more you do it, and get used to doing it, the 
more your brain will automate the task.  You see this type of thing pretty 
often with nurses, for example.

For anyone who would like a better understanding of the science behind 
designing to prevent errors, I recommend the book “Human Error” by James 
Reason.  

Also "The Design of Everyday Things" by Don Norman has a pretty good chapter on 
the basics, and is much more accessible.

I really like that Swift attempts to do this!  The use of forcing functions 
around optionals, for example, is brilliant.  It is just that we are applying 
solutions rather haphazardly (without matching them to the underlying cause of 
error), and I think we can do better.  That we are even considering these 
things is huge!  I am just saying that there is an entire body of scientific 
research we can use to effectively accomplish this goal (and avoid known 
pitfalls)…  we don’t have to reinvent the wheel.

Thanks,
Jon


> On Sep 28, 2017, at 5:31 PM, Jonathan Hull via swift-evolution 
> <swift-evolution@swift.org> wrote:
> 
> +1000
> 
> This is the way it always should have worked… and it is the way my brain 
> still expects it to work.  All of the extraneous “Public”s clutter the code 
> and make it much more difficult to read.  Without it, the relatively few 
> properties marked Internal or Private stand out.
> 
> I know there is the argument about making people think about whether they 
> want to expose each item… but it doesn’t work that way.  Once you assign 
> someone a rote task (assigning Public to most of the things), you lose the 
> effect of having them think.  From a cognitive psychology lens, when you give 
> the brain a number of decisions to make in a row that are very similar, it 
> will naturally make that task more efficient by automating as much of it as 
> possible (i.e. thinking about it less).  Mistakes become much more likely as 
> a result.
> 
> Tl;dr:  Despite the myth/intention that the current setup makes you think 
> about the problem more, it actually does the opposite and leads to an 
> increased risk of error.
> 
> Thanks,
> Jon
> 
> 
>> On Sep 28, 2017, at 10:44 AM, James Valaitis via swift-evolution 
>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>> 
>> When declaring a public class or struct the properties still default to 
>> internal.
>> ```
>> public final class NewType {
>>  /// This property defaults to internal.
>>  var property: Any?
>> }
>> ```
>> 
>> This is not the same for a public extension on the type, where then the 
>> access modifier is respected for any function or calculated property within 
>> the extension.
>> ```
>> public extension NewType {
>>  /// This function inherits the public modifier.
>>  func function() {
>>  }
>> }
>> ```
>> 
>> I dislike this inconsistency, and I frequently find that when using my 
>> dynamic frameworks my code will not compile, and it will be due to my 
>> accidentally writing a public struct but not declaring the properties public.
>> 
>> I believe in the idea that explicitly stating the access modifier leads to 
>> more legible code, but in my opinion it can be overdone, and I much prefer 
>> to explicitly state my intentions in the modifier on the definition or 
>> extension. For example:
>> 
>> ```
>> public struct Coordinate {
>>  /// Should default to public.
>>  let latitude: Double
>>  /// Should default to public.
>>  let longitude: Double
>>  /// Should default to public
>>  init?(latitude: Double, longitude: Double) {
>>  guard validate(latitude: latitude, longitude: longitude) else { 
>> return nil }
>>  …
>>  }
>> }
>> internal extension Coordinate {
>>  /// Convenience initialiser to me used internally within the module.
>>  init(coordinate: CLLocationCoordinate2D) {
>>  …
>>  }
>> }
>> private extension Coordinate {
>>  /// Private validation of the coordinate.
>>  func validate(latitude: Double, longitude: Double) -> Bool {
>>  …
>>  }
>> }
>> ```
>> 
>> This is legible and intuitive. The current behaviour is not.
>> 
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

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


Re: [swift-evolution] Idea: Public Access Modifier Respected in Type Definition

2017-09-28 Thread Jonathan Hull via swift-evolution
+1000

This is the way it always should have worked… and it is the way my brain still 
expects it to work.  All of the extraneous “Public”s clutter the code and make 
it much more difficult to read.  Without it, the relatively few properties 
marked Internal or Private stand out.

I know there is the argument about making people think about whether they want 
to expose each item… but it doesn’t work that way.  Once you assign someone a 
rote task (assigning Public to most of the things), you lose the effect of 
having them think.  From a cognitive psychology lens, when you give the brain a 
number of decisions to make in a row that are very similar, it will naturally 
make that task more efficient by automating as much of it as possible (i.e. 
thinking about it less).  Mistakes become much more likely as a result.

Tl;dr:  Despite the myth/intention that the current setup makes you think about 
the problem more, it actually does the opposite and leads to an increased risk 
of error.

Thanks,
Jon


> On Sep 28, 2017, at 10:44 AM, James Valaitis via swift-evolution 
>  wrote:
> 
> When declaring a public class or struct the properties still default to 
> internal.
> ```
> public final class NewType {
>   /// This property defaults to internal.
>   var property: Any?
> }
> ```
> 
> This is not the same for a public extension on the type, where then the 
> access modifier is respected for any function or calculated property within 
> the extension.
> ```
> public extension NewType {
>   /// This function inherits the public modifier.
>   func function() {
>   }
> }
> ```
> 
> I dislike this inconsistency, and I frequently find that when using my 
> dynamic frameworks my code will not compile, and it will be due to my 
> accidentally writing a public struct but not declaring the properties public.
> 
> I believe in the idea that explicitly stating the access modifier leads to 
> more legible code, but in my opinion it can be overdone, and I much prefer to 
> explicitly state my intentions in the modifier on the definition or 
> extension. For example:
> 
> ```
> public struct Coordinate {
>   /// Should default to public.
>   let latitude: Double
>   /// Should default to public.
>   let longitude: Double
>   /// Should default to public
>   init?(latitude: Double, longitude: Double) {
>   guard validate(latitude: latitude, longitude: longitude) else { 
> return nil }
>   …
>   }
> }
> internal extension Coordinate {
>   /// Convenience initialiser to me used internally within the module.
>   init(coordinate: CLLocationCoordinate2D) {
>   …
>   }
> }
> private extension Coordinate {
>   /// Private validation of the coordinate.
>   func validate(latitude: Double, longitude: Double) -> Bool {
>   …
>   }
> }
> ```
> 
> This is legible and intuitive. The current behaviour is not.
> 
> ___
> 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-09-27 Thread Jonathan Hull via swift-evolution

> On Sep 26, 2017, at 7:31 AM, Xiaodi Wu  wrote:
> 
> Felix and Jonathan make some good points. Some general comments:
> 
> * I think, in general, this area needs a detailed review by those who are 
> expert in the domain; especially if we are to assert that the design is 
> cryptographically secure, we need to ensure that it is actually so. In other 
> words, not just the algorithms that we intend to implement, but the 
> implementations themselves. This is not at all trivial. We will also need to 
> specify whether extension methods that generate certain distributions, etc., 
> are guaranteed secure against side channel attacks where such implementations 
> are known possible but more expensive.
> 
> * Without attempting to bikeshed, the use of the word “Source” is potentially 
> confusing; it could suggest that the conforming type is a source of entropy 
> when in fact it consumes entropy. In my proposed design, the protocol is 
> simply named “PRNG” with an emphasis on the P (i.e. pseudorandom, not random).

This is a good point.  My use of the word “source" in the code I shared (much) 
earlier is because I have a “Source” protocol which essentially represents an 
(effectively) infinite iterator/sequence.  RandomSource is a specific 
sub-protocol I have which provides an infinite iterator/sequence for repeatably 
random numbers.  There are other sources which take an array and cycle it’s 
indices, for example.  I also have a constant source, which always returns the 
same thing.  I use all of this to do cool generative graphical effects.

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

> I disagree here, in two respects:
> 
> First, whether or not a particular PRNG is cryptographically secure is an 
> intrinsic property of the algorithm; whether it's "reproducible" or not is 
> determined by the published API. In other words, the distinction between 
> CSPRNG vs. non-CSPRNG is important to document because it's semantics that 
> cannot be deduced by the user otherwise, and it is an important one for 
> writing secure code because it tells you whether an attacker can predict 
> future outputs based only on observing past outputs. "Reproducible" in the 
> sense of seedable or not is trivially noted by inspection of the published 
> API, and it is rather immaterial to writing secure code. If your attacker can 
> observe your seeding once, chances are that they can observe your reseeding 
> too; then, they can use their own implementation of the PRNG (whether CSPRNG 
> or non-CSPRNG) and reproduce your pseudorandom sequence whether or not Swift 
> exposes any particular API.
> 
> Secondly, I see no reason to justify the notion that, simply because a PRNG 
> is cryptographically secure, we ought to hide the seeding initializer 
> (because one has to exist internally anyway) from the public.


To me, ReproducibleRandomSource has a semantic meaning (more than being a bag 
of methods).  It has an init(seed:) method because you HAVE to be able to seed 
it for reproducibility (not because sources which have a seed would all be 
reproducible).  The fact that RandomSource does not have that requirement 
doesn’t mean you can’t have a source which is seeded… it just allows for 
sources which aren’t.  If something calls itself Reproducible, it should 
actually be reproducible, which includes being able to restore previous states 
(not just the starting seed).


> * The distinction to be made here is CSPRNGs versus non-cryptographically 
> secure PRNGs, where CSPRNG : PRNG. “Reproducible” is not the right word. 
> Based on my understanding, some CSPRNGs can be “reproducible” if the seed is 
> known; what makes it cryptographically secure is that observing its previous 
> *outputs* does not provide information useful to predict future outputs. 
> Along those lines, it may be important to securely delete the seed from 
> memory as soon as possible; there is some way of doing so in C (it’s used in 
> the ChaCha20 reference implementation) but I don’t believe any way of doing 
> so in Swift.

Is CSPRNG vs PRNG really an important distinction for the API?  It is an 
important distinction when choosing a source, of course, but should that be 
reflected in our protocols?  We should definitely make sure that our API does 
not prevent secure/CSPRNGs from working (e.g. not requiring a seed in the base 
API).

Reproducible, on the other hand, is a completely different use-case, which 
requires a different API because it is used differently. We also need to make 
sure our protocol design does not preclude or make difficult these uses.  (We 
just want to avoid people using them 

Re: [swift-evolution] Re-pitch: remove(where:)

2017-09-26 Thread Jonathan Hull via swift-evolution
Er… sorry, by “returns results” I mean, return the removed items.

Thanks,
Jon

> On Sep 26, 2017, at 4:59 PM, Jonathan Hull  wrote:
> 
> The main issue here is that the proposal is missing the variant which returns 
> the elements that are removed… and that throws out a lot of very useful use 
> cases.
> 
>> 1. Is it right to assert that with a “removing” operation, the closure 
>> should return `true` for removal?
> Yes
> 
>> 2. Is it likely that users will want to switch from out-of- to in-place, and 
>> if so, will having to flip the closure cause confusion/bugs?
> They always have the option of just inverting the closure.  I doubt people 
> will change the function being used unless they are doing a larger refactor 
> (or need the removed results).
> 
>> 3. Should we “complete” the matrix of 4 operations, or is it fine for it to 
>> have gaps?
> I am on the fence.  I don’t think gaps will cause an issue, but I could see 
> the usefulness of having more options (but are they worth the upkeep?).
> 
>> 4. If you are for completing, what should X and Y be called?
> removing(where:) and formFilter()  (though I have always been a fan of 
> filter/filtered)
> 
> 
> As I mentioned above, I think that either returning @discardableResults or 
> having a variant which returns the results is very important.  Look at the 
> other thread on this topic from this morning for a discussion of why.
> 
> Thanks,
> Jon
> 
> 
>> On Sep 26, 2017, at 4:12 PM, Ben Cohen via swift-evolution 
>>  wrote:
>> 
>> 
>> Hi everyone,
>> 
>> Reviving a pitch for a feature that didn’t make it into Swift 4. This was 
>> discussed in the core team recently, and feedback was wanted regarding the 
>> naming of the method and the polarity of the where closure.
>> 
>> Here’s the proposal:
>> 
>> https://github.com/airspeedswift/swift-evolution/blob/0f4a24d6ded2ab7cb39c1a68e0f92705a7615d73/proposals/-RemoveWhere.md
>> 
>> To keep things simple, this version removes the Equatable version. That 
>> could be added as a separate proposal.
>> 
>> 
>> The issue to resolve is: should the closure have the same polarity as 
>> filter, and if not, should filter also have an in-place equivalent?
>> (wait, don’t reply yet, read the rest of the email first :)
>> 
>> From the original proposal:
>> 
>>> `remove(where:)` takes a closure with `true` for elements to remove. 
>>> `filter` takes a closure with `true` for elements to keep. In both cases, 
>>> `true` is the "active" case, so likely to be what the user wants without 
>>> having to apply a negation. The naming of `filter` is unfortunately 
>>> ambiguous as to whether it’s a removing or keeping operation, but 
>>> re-considering that is outside the scope of this proposal.
>> 
>> 
>> Assuming you accept the premise that a closure returning `true` to `remove` 
>> is the “right way around” for the argument to an in-place removal operation, 
>> this means that we have a situation where if you want to flip from in-place 
>> to out-of-place removal, you have to reverse the closure.
>> 
>> Alternatively, we could duplicate the functionality, and have both filter 
>> and remove operations have in- and out-of-place variants, completing this 
>> 2x2 matrix:
>> 
>> out-of-place, true to keep:  filter(_:)
>> in-place, true to remove:remove(where:)
>> out-of-place, true to remove:X?
>> in-place, true to keep:  Y?
>> 
>> The names for X that fall easily out of the naming guidelines are 
>> removed(where:) or removing(where:)
>> 
>> Y is trickier. Normally, the out-of-place would be a variant (like the past 
>> participle) of the mutating operation, but with filter the out-of-place 
>> method is already named,* so options are limited. formFilter(_:) is one 
>> suggestion.
>> 
>> 
>> To help guide feedback on this, here are 4 questions to answer:
>> 
>> 1. Is it right to assert that with a “removing” operation, the closure 
>> should return `true` for removal?
>> 2. Is it likely that users will want to switch from out-of- to in-place, and 
>> if so, will having to flip the closure cause confusion/bugs?
>> 3. Should we “complete” the matrix of 4 operations, or is it fine for it to 
>> have gaps?
>> 4. If you are for completing, what should X and Y be called?
>> 
>> Any answers, or further thoughts on any of the above, appreciated.
>> 
>> Ben
>> 
>> 
>> 
>> * while you could argue that this can be resolved by renaming filter, 
>> renames like this have a very high bar to clear. Also, filter is a term of 
>> art, hence its previous exemption from the naming guidelines.
>> 
>> 
>> ___
>> 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] Re-pitch: remove(where:)

2017-09-26 Thread Jonathan Hull via swift-evolution
The main issue here is that the proposal is missing the variant which returns 
the elements that are removed… and that throws out a lot of very useful use 
cases.

> 1. Is it right to assert that with a “removing” operation, the closure should 
> return `true` for removal?
Yes

> 2. Is it likely that users will want to switch from out-of- to in-place, and 
> if so, will having to flip the closure cause confusion/bugs?
They always have the option of just inverting the closure.  I doubt people will 
change the function being used unless they are doing a larger refactor (or need 
the removed results).

> 3. Should we “complete” the matrix of 4 operations, or is it fine for it to 
> have gaps?
I am on the fence.  I don’t think gaps will cause an issue, but I could see the 
usefulness of having more options (but are they worth the upkeep?).

> 4. If you are for completing, what should X and Y be called?
removing(where:) and formFilter()  (though I have always been a fan of 
filter/filtered)


As I mentioned above, I think that either returning @discardableResults or 
having a variant which returns the results is very important.  Look at the 
other thread on this topic from this morning for a discussion of why.

Thanks,
Jon


> On Sep 26, 2017, at 4:12 PM, Ben Cohen via swift-evolution 
>  wrote:
> 
> 
> Hi everyone,
> 
> Reviving a pitch for a feature that didn’t make it into Swift 4. This was 
> discussed in the core team recently, and feedback was wanted regarding the 
> naming of the method and the polarity of the where closure.
> 
> Here’s the proposal:
> 
> https://github.com/airspeedswift/swift-evolution/blob/0f4a24d6ded2ab7cb39c1a68e0f92705a7615d73/proposals/-RemoveWhere.md
> 
> To keep things simple, this version removes the Equatable version. That could 
> be added as a separate proposal.
> 
> 
> The issue to resolve is: should the closure have the same polarity as filter, 
> and if not, should filter also have an in-place equivalent?
> (wait, don’t reply yet, read the rest of the email first :)
> 
> From the original proposal:
> 
>> `remove(where:)` takes a closure with `true` for elements to remove. 
>> `filter` takes a closure with `true` for elements to keep. In both cases, 
>> `true` is the "active" case, so likely to be what the user wants without 
>> having to apply a negation. The naming of `filter` is unfortunately 
>> ambiguous as to whether it’s a removing or keeping operation, but 
>> re-considering that is outside the scope of this proposal.
> 
> 
> Assuming you accept the premise that a closure returning `true` to `remove` 
> is the “right way around” for the argument to an in-place removal operation, 
> this means that we have a situation where if you want to flip from in-place 
> to out-of-place removal, you have to reverse the closure.
> 
> Alternatively, we could duplicate the functionality, and have both filter and 
> remove operations have in- and out-of-place variants, completing this 2x2 
> matrix:
> 
> out-of-place, true to keep:   filter(_:)
> in-place, true to remove: remove(where:)
> out-of-place, true to remove: X?
> in-place, true to keep:   Y?
> 
> The names for X that fall easily out of the naming guidelines are 
> removed(where:) or removing(where:)
> 
> Y is trickier. Normally, the out-of-place would be a variant (like the past 
> participle) of the mutating operation, but with filter the out-of-place 
> method is already named,* so options are limited. formFilter(_:) is one 
> suggestion.
> 
> 
> To help guide feedback on this, here are 4 questions to answer:
> 
> 1. Is it right to assert that with a “removing” operation, the closure should 
> return `true` for removal?
> 2. Is it likely that users will want to switch from out-of- to in-place, and 
> if so, will having to flip the closure cause confusion/bugs?
> 3. Should we “complete” the matrix of 4 operations, or is it fine for it to 
> have gaps?
> 4. If you are for completing, what should X and Y be called?
> 
> Any answers, or further thoughts on any of the above, appreciated.
> 
> Ben
> 
> 
> 
> * while you could argue that this can be resolved by renaming filter, renames 
> like this have a very high bar to clear. Also, filter is a term of art, hence 
> its previous exemption from the naming guidelines.
> 
> 
> ___
> 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-09-26 Thread Jonathan Hull via swift-evolution
Instead of “UnsafeRandomSource”, I would call it “ReproducibleRandomSource”.  I 
have also found that you often need to be able to “rewind” a reproducible 
random source for graphics applications:

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

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

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

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

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

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

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

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

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

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

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

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

Thanks,
Jon


> On Sep 25, 2017, at 9:57 PM, Alejandro Alonso via swift-evolution 
>  wrote:
> 
> Hello evolution,
> 
> I am very thankful for all the feedback, and I’ve been working on a design 
> that tries to utilize everybody’s ideas. The link to what I have so far is 
> here: https://gist.github.com/Azoy/15f0518df38df9b722d4cb17bafea4c1 
> . Please keep 
> in mind this is just a design, no actual implementation as I would most 
> likely need assistance in doing. The default source for randomness will use 
> the OS’s unseeded CSPRNG. This current setup exposes developers to an API 
> that lets them create their own RandomSources on the fly. I want to make the 
> distinction that any existing or new sources of randomness that conform to 
> UnsafeRandomSource are to be considered non cryptographically secure.
> 
> I would love to get this discussion flowing again, and I would love input on 
> the design. A few things I came across with this design is that some may want 
> to use ranges as an argument for the numeric types, RandomAccessCollection 
> returning an optional when getting a random, and how to incorporate an API 
> that allows distributions. I wanted to get input on how you feel about each 
> of these topics as I’m indifferent about them all. I’m in no way saying this 
> is the design we should go for, but I’m simply providing something I think we 
> should build on or talk about.
> 
> - Alejandro
> 
> On Sep 8, 2017, 11:52 AM -0500, Alejandro Alonso via swift-evolution 
> , 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

Re: [swift-evolution] Additional methods for removing elements from a collection in Swift

2017-09-26 Thread Jonathan Hull via swift-evolution
Alwyn just pointed out another use-case as well.

If there is either a @discardableResult or two variants (one which returns a 
result) where the method returns the items being removed (which is to be 
expected of a method named “remove”), then it becomes useful in ways which 
filter alone is not.  Here is how it would be used with a use-case from a 
project I was working on this weekend:

var longWords = allWords //A very long list of words passed as a 
parameter
let shortWords = longWords.remove(where: {$0.characters.count < 4})

compare that to either filtering twice:

let longWords = allWords.filter({$0.characters.count >= 4})
let shortWords = allWords.filter({$0.characters.count < 4}) //We are 
looping over a very long list twice

or what I ended up doing:

var longWords:[String] = []
var shortWords:[String] = []
for word in allWords {
if word.characters.count < 4 {
shortWords.append(word)
}else{
longWords.append(word)
}
}


Thanks,
Jon

> On Sep 26, 2017, at 2:59 AM, Xiaodi Wu  wrote:
> 
> 
> On Tue, Sep 26, 2017 at 00:15 Jonathan Hull  > wrote:
> As he says, it is an in-place equivalent of filter, so the use-cases would be 
> similar.  I could see this being extremely useful.  Off the top of my head:
> 
>   views.remove(where: {$0.isHidden}) //Remove all views which are hidden 
> from the list.
> 
> Is such a method ever going to be different (in performance, say) from:
> 
> views = Views(views.lazy.filter { $0.isHidden })
> 
> Another thing which seems to be missing (although it could be there and I 
> don’t know the name) is the ability to split a list into two using a filter 
> (one with the filtered items and one with the remainder).  I am surprised 
> every time I reach for it and it isn’t there (the last time being yesterday). 
>  
> 
> Thanks,
> Jon
> 
> 
> 
>> On Sep 25, 2017, at 9:55 PM, Xiaodi Wu via swift-evolution 
>> > wrote:
>> 
>> What is the use case?
>> On Mon, Sep 25, 2017 at 23:27 Félix Cloutier > > wrote:
>> Actually, IMO, it's an oversight that there's no remove(where:), or another 
>> in-place equivalent to `filter`. I'm in favor of it.
>> 
>> Félix
>> 
>> 
>>> Le 25 sept. 2017 à 15:17, Xiaodi Wu >> > a écrit :
>>> 
>>> On Mon, Sep 25, 2017 at 4:55 PM, Xiaodi Wu >> > wrote:
>>> Brent has a great proposal in the pipeline regularizing the names of some 
>>> of these functions and filling in some of the more glaring gaps.
>>> 
>>> With regard to the specific items proposed here, Felix shows that ‘filter’ 
>>> provides an idiomatic one-line way of doing some of what is proposed; 
>>> currently remove(index(of:)) and operating on sliced would accomplish the 
>>> rest. Therefore, I do not think these proposed additions meet the very high 
>>> bar for expansion of the standard library API.
>>> 
>>> I should add, however, it is wonderful (IMO) that more people are thinking 
>>> about these APIs; welcome and thank you for restarting this very important 
>>> conversation. It would be nice to get some more eyeballs on the previously 
>>> discussed set of rationalizations to the Collection APIs so that we can 
>>> make their use a little more ergonomic--with any luck, some better names 
>>> for existing extension methods and filling in a very few gaps judiciously 
>>> would allow us to make the existing facilities sufficiently more 
>>> discoverable that it will be easier to accomplish what you seek without 
>>> adding more extensions.
>>> 
>>> 
>>> On Mon, Sep 25, 2017 at 11:14 Félix Cloutier via swift-evolution 
>>> > wrote:
>>> Another alternative is to use `array = array.filter { $0 != someElement }`.
>>> 
>>> I thought that there would be a `remove(where:)` method, but there isn't.
>>> 
>>> Félix
>>> 
 Le 25 sept. 2017 à 02:12, Alwyn Concessao via swift-evolution 
 > a écrit :
 
 Hello,
 
 After going through the Swift standard library functions provided for 
 removing elements from a collection, one common pattern can be observed in 
 all those functions and that is the functions provide to remove elements 
 from the collection by passing the position or index of the element or 
 passing a range of indices or positions to remove the elements.The 
 standard library does not provide options to remove an element from a 
 collection by passing the actual element  to be removed directly to the 
 remove method.I've encountered this situation many times when programming 

Re: [swift-evolution] Additional methods for removing elements from a collection in Swift

2017-09-26 Thread Jonathan Hull via swift-evolution

> On Sep 26, 2017, at 2:37 AM, Alwyn Concessao  wrote:
> 
> @Jonathan Hull - You've mentioned  about splitting a list using a filter 
> which returns the filtered list and the remainder.Is it similar to having a 
> filter function which does the filtering on the original collection and also 
> returns the elements which are removed from the collection?

Hmm… I suppose a remove(where:) that had a @discardableResult of the things 
being removed would be useful in this way.  Not to mention that it would be 
consistent with what I expect from a function called remove.

I was already in support, but now even more so…

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


Re: [swift-evolution] Additional methods for removing elements from a collection in Swift

2017-09-25 Thread Jonathan Hull via swift-evolution
As he says, it is an in-place equivalent of filter, so the use-cases would be 
similar.  I could see this being extremely useful.  Off the top of my head:

views.remove(where: {$0.isHidden}) //Remove all views which are hidden 
from the list.

Another thing which seems to be missing (although it could be there and I don’t 
know the name) is the ability to split a list into two using a filter (one with 
the filtered items and one with the remainder).  I am surprised every time I 
reach for it and it isn’t there (the last time being yesterday).  

Thanks,
Jon


> On Sep 25, 2017, at 9:55 PM, Xiaodi Wu via swift-evolution 
>  wrote:
> 
> What is the use case?
> On Mon, Sep 25, 2017 at 23:27 Félix Cloutier  > wrote:
> Actually, IMO, it's an oversight that there's no remove(where:), or another 
> in-place equivalent to `filter`. I'm in favor of it.
> 
> Félix
> 
> 
>> Le 25 sept. 2017 à 15:17, Xiaodi Wu > > a écrit :
>> 
>> On Mon, Sep 25, 2017 at 4:55 PM, Xiaodi Wu > > wrote:
>> Brent has a great proposal in the pipeline regularizing the names of some of 
>> these functions and filling in some of the more glaring gaps.
>> 
>> With regard to the specific items proposed here, Felix shows that ‘filter’ 
>> provides an idiomatic one-line way of doing some of what is proposed; 
>> currently remove(index(of:)) and operating on sliced would accomplish the 
>> rest. Therefore, I do not think these proposed additions meet the very high 
>> bar for expansion of the standard library API.
>> 
>> I should add, however, it is wonderful (IMO) that more people are thinking 
>> about these APIs; welcome and thank you for restarting this very important 
>> conversation. It would be nice to get some more eyeballs on the previously 
>> discussed set of rationalizations to the Collection APIs so that we can make 
>> their use a little more ergonomic--with any luck, some better names for 
>> existing extension methods and filling in a very few gaps judiciously would 
>> allow us to make the existing facilities sufficiently more discoverable that 
>> it will be easier to accomplish what you seek without adding more extensions.
>> 
>> 
>> On Mon, Sep 25, 2017 at 11:14 Félix Cloutier via swift-evolution 
>> > wrote:
>> Another alternative is to use `array = array.filter { $0 != someElement }`.
>> 
>> I thought that there would be a `remove(where:)` method, but there isn't.
>> 
>> Félix
>> 
>>> Le 25 sept. 2017 à 02:12, Alwyn Concessao via swift-evolution 
>>> > a écrit :
>>> 
>>> Hello,
>>> 
>>> After going through the Swift standard library functions provided for 
>>> removing elements from a collection, one common pattern can be observed in 
>>> all those functions and that is the functions provide to remove elements 
>>> from the collection by passing the position or index of the element or 
>>> passing a range of indices or positions to remove the elements.The standard 
>>> library does not provide options to remove an element from a collection by 
>>> passing the actual element  to be removed directly to the remove 
>>> method.I've encountered this situation many times when programming in Swift 
>>> wherein I want an element or a set of elements to be removed directly 
>>> without always accessing it's index in the collection but I have always 
>>> ended up having to first access the index of the element or elements which 
>>> I want to remove and then pass that index to the remove method.
>>> 
>>> The idea is to have an extension of the RangeReplaceableCollection protocol 
>>> to include a method to remove elements from a collection by passing 
>>> directly the element to be removed to the remove method and also include 
>>> methods to remove multiple elements from the collection by passing in a 
>>> sequence of the elements to be removed to the remove method and to remove 
>>> an element in a particular subrange of the collection.
>>> 
>>> The prototype of the methods will be as follows - 
>>> 
>>> extension RangeReplaceableCollection where Element:Equatable{
>>> 
>>> mutating func removeElement(_ elementToBeRemoved:Element){
>>> 
>>> //check if elementToBeRemoved exists ;if yes, remove all occurrences of 
>>> elementsToBeRemoved from the collection.
>>> 
>>> }
>>> 
>>> mutating func removeElementInSubrange(_ elementToBeRemoved:Element,in 
>>> range:Range){
>>> 
>>> //check if elementoBeRemoved exists; if yes, check if the index of 
>>> elementToBeRemoved is part of the subrange, if yes then remove else don't 
>>> remove.
>>> 
>>> }
>>> 
>>> mutating func removeContentsOf(_ elementsToBeRemoved:C){
>>> 
>>> //check if each element in the elementsToBeRemoved sequence exists in the 
>>> collection, if the element 

Re: [swift-evolution] (core library) modern URL types

2017-09-21 Thread Jonathan Hull via swift-evolution
Looks like the author posted a free copy of the paper here:
http://www.hirschfeld.org/writings/media/WeiherHirschfeld_2013_PolymorphicIdentifiersUniformResourceAccessInObjectiveSmalltalk_AcmDL.pdf

Thanks,
Jon

> On Sep 20, 2017, at 10:03 PM, Thorsten Seitz via swift-evolution 
>  wrote:
> 
> 
> Am 24.08.2017 um 23:07 schrieb Eagle Offshore via swift-evolution 
> >:
> 
>> I liked the polymorphic identifiers paper presented at Dynamic Languages 
>> Symposium 2013.
>> 
>> http://dl.acm.org/citation.cfm?doid=2508168.2508169 
>> 
>> There's a lot of power in URI's that remains largely untapped in most 
>> systems.
>> 
>> There's not a great reason for this heterogeneity other than historical 
>> baggage.
>> 
>> Properly done, URI's can unify keypaths, user defaults, environment 
>> variables, files, network stores, databases, etc.
> 
> Would you mind summarizing the idea as the paper is not freely available?
> 
> -Thorsten
> 
> 
>>> On Aug 22, 2017, at 12:52 PM, Félix Cloutier via swift-evolution 
>>> > wrote:
>>> 
>>> Just leaving it out here that the iOS/macOS app experience with paths is 
>>> likely to be very different from the server (or system program) experience. 
>>> Most of your paths are relative to a container because the effective root 
>>> of your data is the container. I would tend to believe that a lot of your 
>>> paths, not while fully static, could be expressed with something like 
>>> "${DOCUMENTS}/static/part", where ${DOCUMENTS} is the only thing that 
>>> effectively changes. A system-level program just happens to use / as its 
>>> prefix.
>>> 
>>> Most platforms already have some notion of file domains, which are really 
>>> just path prefixes (the user's home folder, the file system root, the 
>>> network root, etc). I think that some level of support for these would be 
>>> desirable (would it be only a set of functions that return different path 
>>> prefixes). It's also my humble opinion that tilde expansion should be part 
>>> of a larger shell expansion feature to avoid surprises.
>>> 
>>> I think that I support the conclusion.
>>> 
>>> Félix
>>> 
>>> Le 22 août 2017 à 12:02, Dave DeLong >> > a écrit :
>>> 
 I suppose, if you squint at it weirdly.
 
 My current Path API is a “Path” protocol, with “AbsolutePath” and 
 “RelativePath” struct versions. The protocol defines a path to be an array 
 of path components. The only real difference between an AbsolutePath and a 
 RelativePath is that all file system operations would only take an 
 AbsolutePath. A URL would also only provide an AbsolutePath as its “path” 
 bit.
 
 public enum PathComponent {
 case this // “."
 case up   // “..” 
 case item(name: String, extension: String?)
 }
 
 public protocol Path {   
 var components: Array { get }
 init(_ components: Array) // used on protocol 
 extensions that mutate paths, such as appending components
 }
 
 public struct AbsolutePath: Path { }
 public struct RelativePath: Path { }
 
 By separating out the concept of an Absolute and a Relative path, I can 
 put additional functionality on each one to make semantic sense (you 
 cannot concatenate two absolute paths, but you can concat any path with a 
 relative path, for example). Or all file system operations must take an 
 AbsolutePath. 
 
 One of the key things I realized is that a “Path” type should not be 
 ExpressibleByStringLiteral, because you cannot statically determine if a 
 Path should be absolute or relative. However, one of the initializers for 
 an AbsolutePath would handle things like expanding a tilde, and both types 
 try to reduce a set of components as much as possible (by filtering out 
 “.this” components, and handling “.up” components where possible, etc). 
 Also in my experience, it’s fairly rare to want to deal with a 
 known-at-compile-time, hard-coded path. Usually you’re dealing with paths 
 relative to known “containers” that are determined at runtime (current 
 user’s home folder, app’s sandboxed documents directory, etc).
 
 Another thing I’ve done is that no direct file system operations exist on 
 AbsolutePath (like “.exists” or “.createDirectory(…)” or whatever); those 
 are still on FileManager/FileHandle/etc in the form of extensions to 
 handle the new types. In my app, a path is just a path, and it only has 
 meaning based on the thing that is using it. An AbsolutePath for a URL is 
 used differently than an AbsolutePath on a file system, although they are 
 represented with the same “AbsolutePath” type.
 
 I’m not saying this is a perfect API 

Re: [swift-evolution] Enums and Source Compatibility

2017-09-17 Thread Jonathan Hull via swift-evolution
Ah, ok.  I had missed this too, somehow.

> On Sep 17, 2017, at 4:04 PM, BJ Homer via swift-evolution 
>  wrote:
> 
> Please note that, as proposed, enums are always treated as exhaustive *within 
> the same module*. A new user writing MyFirstEnum is likely using it within 
> the same module, and will thus get exhaustive behavior with no extra keywords 
> required.
> 
> -BJ
> 
> On Sep 17, 2017, at 3:20 PM, Christopher Kornher via swift-evolution 
> > wrote:
> 
>> 
>>> On Sep 17, 2017, at 6:33 AM, Rod Brown via swift-evolution 
>>> > wrote:
>>> 
>>> 
 On 17 Sep 2017, at 4:35 am, Christopher Kornher > wrote:
 
> On Sep 16, 2017, at 11:28 AM, Christopher Kornher via swift-evolution 
> > wrote:
> 
> If a library writer can’t remember to declare non-exhaustive enums as 
> such, they probably will forget many more important aspects of creating a 
> library. They probably should not be writing libraries. Arguments like 
> this make sense on the surface, but creating libraries involves hundreds 
> or thousands of decisions. I wish you luck in making that process idiot 
> proof. A library linter could easily warn that exposed enums are 
> exhaustive. The exhaustive keyword should be optional to make the 
> decision obvious and suppress warnings. Complicating the user experience 
> in a vain attempt to make “expert" coding safer is misguided.
>>> 
>>> I think the same logic goes both ways: If a library author can’t remember 
>>> to declare exhaustive enums as such, they will probably forget many more 
>>> important aspects of creating a library.
>>> 
>>> The problem here is fundamental: Exhaustive is a guarantee. A guarantee 
>>> should require action. Non-Exhaustive guarantees nothing. It makes you 
>>> safer. That is all.
>> 
>> 1) Exhaustive enums are inherently better: they allow a developer to know 
>> that they have covered all possible cases by not using a default.
>> 2) This proposal forces developers to add a keyword to get this behavior in 
>> their apps, which is common to all other languages with enums that I have 
>> used. This proposal breaks the model common to all (?) current 
>> implementations of enums. 
>> 
>> 
>>> 
 
 This may be a little harsh, but there don’t seem to be many advocates for 
 novice and “ordinary” application developers on this list. That is not 
 unexpected given the number of extremely knowledgeable compiler and 
 library developers on this list (for whom I have the highest respect). I 
 believe that there are more creative (and probably more difficult to 
 build) possible solutions to some of the tough problems in Swift’s future. 
 In that spirit, see below.
>>> 
>>> I personally am an “ordinary” application developer.
>>> 
>>> I think the issue here is that everyone is seeing Swift as *they* intend to 
>>> use it. For App Devs, exhaustive switches are nice, which means they really 
>>> are fighting tooth and nail to keep them. I understand that. But I’m also 
>>> trying to keep my mind open for “what happens to an app I compiled in iOS 
>>> 15 that I compiled for iOS 11?” And this gives me pause. I can’t ask Apple 
>>> or any other library author to be completely knowledgable about every case 
>>> in the future, and to audit every line of code and manually give 
>>> non-exhaustive.
>>> 
>>> Why do people want “exhaustive” to be the default?
>>> Because we like things as they are.
>> 
>> No, because it makes sense to make common things easy and uncommon things 
>> possible. 
>> 
>>> Because we like not having to consider edge cases. Because we want to 
>>> imagine that will give framework developers the control to make our lives 
>>> difficult because they’ll just be lazy and make our lives hard by not 
>>> annotating. And this certainly is a concern. But I think a larger concern 
>>> is breaking apps left, right and centre, or not being able to extend 
>>> frameworks because an earlier developer on a project made an oversight.
>> 
>> This happens all the time: Apple deprecates APIs and asked developers to use 
>> new ones. If a library writer does not run (the as-yet hypothetical ) 
>> library lint, not participate in thorough code reviews,…, they can simply 
>> create a new non-exhaustive enum and deprecate the old one. Yes, there will 
>> be some redundant function calls for a while, but again, similar things 
>> happen, even in APIs like Apple’s, that (one hopes, at least) are thoroughly 
>> reviewed. It is not the end of the world to deprecate and migrate APIs. You  
>> may remember garbage collected Objective-C, the change that “viewWillAppear” 
>> suddenly was not called when it used to be in iOS. We all survived the 
>> 

Re: [swift-evolution] Enums and Source Compatibility

2017-09-17 Thread Jonathan Hull via swift-evolution

> On Sep 17, 2017, at 7:55 AM, Matthew Johnson <matt...@anandabits.com> wrote:
> 
> 
> 
> Sent from my iPad
> 
> On Sep 17, 2017, at 3:37 AM, Jonathan Hull via swift-evolution 
> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
> 
>> I run into use cases like this all the time…
>> 
>> I think I would prefer to see those concrete cases in a subtype though:
>> 
>>  enum DrinkSize {
>>  case small
>>  case medium
>>  case large
>>  }
>> 
>>  enum SummerDrinkSize : DrinkSize {
>>  //Inherits DrinkSize’s cases
>>  case extraLarge
>>  }
>> 
>> Because it is a subtype, you could place a SummerDrinkSize anywhere you can 
>> put a DrinkSize.  As a result, all switches on it would need a default case 
>> to handle cases they hadn’t planned for. If you mark an enum with “final” 
>> then it can’t be extended and switches can be exhaustive.
> 
> You have the subtype relationship backwards here.  DrinkSize is a subtype of 
> SummerDrinkSize.  All values of DrinkSize are also valid values of 
> SummerDrinkSize but not vice versa.  For this reason, inheritance syntax 
> doesn't make sense.  The syntax that makes more sense is some kind of case 
> embedding syntax:
> 
> enum SummerDrinkSize {
>   cases DrinkSize
>   case extraLarge
> }

I disagree.  I get that the shape of a DrinkSize would always fit in a 
SummerDrinkSize hole (ignoring the overriding/extension of methods), but the 
fact that we are requiring ‘default’ in switches changes the calculus.  
Basically, it changed when we decided to change whether exhaustive was the 
default.  The point is to make people consider that they may have cases which 
they may not expect.  That is much easier with a concrete idea of subtype, 
which people are already used to.


>> 
>> In addition to inheriting the cases, a subtype would also inherit, and be 
>> able to override, methods defined on the super-type.  You could use super to 
>> call the super-type’s implementation. 
> 
> I think implementation sharing is a bad idea for value types.  Value 
> subtyping should be conceptualized as a restricted mechanism for 
> value-preserving implicit conversion.

Why?


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


Re: [swift-evolution] Enums and Source Compatibility

2017-09-17 Thread Jonathan Hull via swift-evolution

> On Sep 16, 2017, at 11:35 AM, Christopher Kornher via swift-evolution 
>  wrote:
> 
> This may be a little harsh, but there don’t seem to be many advocates for 
> novice and “ordinary” application developers on this list. That is not 
> unexpected given the number of extremely knowledgeable compiler and library 
> developers on this list (for whom I have the highest respect). I believe that 
> there are more creative (and probably more difficult to build) possible 
> solutions to some of the tough problems in Swift’s future.

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


Re: [swift-evolution] Enums and Source Compatibility

2017-09-17 Thread Jonathan Hull via swift-evolution
I run into use cases like this all the time…

I think I would prefer to see those concrete cases in a subtype though:

enum DrinkSize {
case small
case medium
case large
}

enum SummerDrinkSize : DrinkSize {
//Inherits DrinkSize’s cases
case extraLarge
}

Because it is a subtype, you could place a SummerDrinkSize anywhere you can put 
a DrinkSize.  As a result, all switches on it would need a default case to 
handle cases they hadn’t planned for. If you mark an enum with “final” then it 
can’t be extended and switches can be exhaustive.

In addition to inheriting the cases, a subtype would also inherit, and be able 
to override, methods defined on the super-type.  You could use super to call 
the super-type’s implementation. 

It is a bigger overhaul, but I think it actually ends up being semantically 
simpler for the end user.  Basically, you can do the same types of things you 
can with classes... with the same syntax (just without the reference-type-ness).

It just so happens that this would also solve the problem of adding cases to 
(non-final) library enums, because switches of the enums would need to handle 
default/unexpected cases.  That is a very abstract/confusing problem for end 
users who don’t write libraries to understand though.  I think it is much 
easier to explain “final” as being the same as it is in classes, in that it 
prevents subclassing… which means you know what all the cases are.

More work (also more powerful), but semantically simpler. It just combines 
concepts we already know...

Thanks,
Jon


> On Sep 16, 2017, at 3:51 PM, Kenny Leung via swift-evolution 
>  wrote:
> 
> Oops, forgot something:
> 
> "Can there be a kind of open enum where you can add new cases in extensions?”
> 
> I have a use case for this. I’m trying to write a database ORM with abstract 
> API and concrete instances for different database. So I have defined:
> 
> open class Database {
>init(connectionDictionary: [ConnectionDictionaryKey:String]) {
> self.connectionDictionary = connectionDictionary;
> }
> }
> 
> Where I have ConnectionDictionaryKey defined as an enum, with values like 
> .hostName, .databaseName, .userName, .password, .databaseName, etc…
> 
> But concrete databases may have other options that need to be added to the 
> connection dictionary. It would be nice if they could just extend 
> ConnectionDictionaryKey with new cases.
> 
> -Kenny
> 
> 
>> On Sep 16, 2017, at 3:35 PM, Kenny Leung via swift-evolution 
>> > wrote:
>> 
>> In general, I agree with everything in the proposal.
>> 
>> I’d like to propose these alternative extensions for clients:
>> 
>> 1) As a client of an enum, I’d like to know in the future when a new value 
>> has been added to an enum, since I may have to do something about it. How 
>> about adding the “exhaustive” keyword to be used in the switch statement? 
>> Like
>> 
>> exhaustive switch excuse {
>> case eatenByPet:
>> // …
>> case thoughtItWasDueNextWeek:
>> // …
>> default:
>> // …
>> }
>> 
>> If exhaustive is used, there would be a warning if all cases aren’t covered 
>> *even though default exists*. This means that I as the client thought I had 
>> everything covered when I wrote this code.
>> 
>> As already mentioned, this makes the default case un-testable, which brings 
>> me to
>> 
>> 2) All non-exhaustive enums should have the pseudo value “default” that can 
>> be used just like a regular value. This would allow you to write code like:
>> 
>> teacher.failedToHandInHomework(excuse: .default)
>> 
>> which would allow you to trip the default case in any code you may write.
>> 
>> -Kenny
>> 
>> 
>>> On Sep 13, 2017, at 12:17 PM, Jordan Rose via swift-evolution 
>>> > wrote:
>>> 
>>> Proposal updated, same URL: 
>>> https://github.com/jrose-apple/swift-evolution/blob/non-exhaustive-enums/proposals/-non-exhaustive-enums.md
>>>  
>>> .
>>> 
>>> Thanks again for all the feedback so far, everyone!
>>> Jordan
>>> 
>>> 
 On Sep 12, 2017, at 17:55, Jordan Rose via swift-evolution 
 > wrote:
 
 Sorry, I got distracted by other tasks! Both the discussion here and 
 within Apple has moved towards making "non-exhaustive" the default, which, 
 to be honest, I too think is the best design. I'll update the proposal 
 today to reflect that, though I still want to keep both the 
 "nonexhaustive" and "exhaustive" keywords for Swift 4 compatibility for 
 now (or whatever we end up naming them). The compatibility design is a 
 little less ambitious than 

Re: [swift-evolution] [Proposal] Explicit Synthetic Behaviour

2017-09-11 Thread Jonathan Hull via swift-evolution
What if we tried a completely different type of solution (which might solve the 
issue for protocol default conformances too)?

Right now there are errors and warnings.  What if we add a third type of 
compiler feedback (let’s call it a note).  A note is a little bit like a 
warning, but it can be dismissed/acknowledged.  It is only generated once for a 
particular issue, and then it is remembered that you dismissed it so it won’t 
come back every time you compile.

So in this case, when you add an Equatable conformance post-hoc, you get a note 
(let’s say it looks like a warning, but is grey instead of yellow and has a 
different icon) saying something like “Equatable conformance was automatically 
synthesized”.  If you want to remember to add your own conformance, you can 
just leave the note there as a reminder to yourself until you do it.  If you 
want the automatic conformance then you just dismiss the note and it never 
bothers you again.

Thanks,
Jon

> On Sep 7, 2017, at 12:52 PM, Xiaodi Wu via swift-evolution 
>  wrote:
> 
> This is a particularly interesting use case that demonstrates a weakness 
> without a good workaround. I, for one, am glad you brought it up, and agree 
> with comments above that auto-generated mandatory enum conformance is a topic 
> perhaps worth revisiting, given this compelling example.
> On Thu, Sep 7, 2017 at 14:32 Gwendal Roué via swift-evolution 
> > wrote:
> 
>> Le 7 sept. 2017 à 19:53, Tony Allevato > > a écrit :
>> 
>> Again, this is not the issue that Haravikk is describing in this thread.
> 
> Yes, I better understand now. Please forgive the pollution.
> 
> Gwendal
> 
> ___
> 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


  1   2   3   4   5   >