[swift-evolution] [Accepted] SE-0158 Package Manager Manifest API Redesign

2017-03-16 Thread Rick Ballard via swift-evolution
Proposal Link: 
https://github.com/apple/swift-evolution/blob/master/proposals/0158-package-manager-manifest-api-redesign.md

The review of SE-0158 "Package Manager Manifest API Redesign" ran from March 7 
until March 15. The proposal is accepted with the following revisions:

– The "To" in "upToNextMajor" and "upToNextMinor" will be capitalized.
– "upToNextMajor()" and "upToNextMinor()" will name the first parameter "from:" 
for clarity.
– ".only" will be removed, as it was duplicative versus ".exact".
– We will have cases for ".branch" and ".revision" version specifiers, but will 
not provide special package initializers with named parameters for these.

This proposal was generally supported, though it did require some discussion 
and minor revision, and some users are eager for future proposals adding new 
API not covered by this proposal.

Thanks to everyone who participated!

- Rick Ballard

Review Manager

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


Re: [swift-evolution] [Proposal] Foundation Swift Archival & Serialization

2017-03-16 Thread Slava Pestov via swift-evolution

> On Mar 16, 2017, at 4:00 PM, Matthew Johnson via swift-evolution 
>  wrote:
> 
> 
> 
> Sent from my iPad
> 
>> On Mar 16, 2017, at 5:54 PM, Ben Rimmington  wrote:
>> 
>> 
 On 16 Mar 2017, at 21:14, Matthew Johnson wrote:
 
 On Mar 16, 2017, at 4:12 PM, Itai Ferber  wrote:
 
 If throwing subscripts made it in the Swift 4 timeframe, then we would 
 certainly consider it.
>>> 
>>> Cool.  Any comment from the core team on whether this is a possibility?  If 
>>> it is and nobody else wants to write a proposal I would be willing to do it.
>> 
>> "Throwing Properties and Subscripts" proposal by Brent Royal-Gordon (12 
>> months ago):
>> 
>> 
> 
> Oh, great!  I had forgotten about this.  It would be awesome if we could 
> revive this for Swift 4 especially so it can be considered as part of the 
> interface of this API.  Even if Foundation doesn't adopt the, they would be a 
> great complement for those of us who would prefer the lighter syntax and are 
> willing to use our own wrapper.

I think the limiting factor here is not reviewing the proposal, but 
implementing it. If someone comes up with a prototype implementation it would 
increase the odds of the proposal being accepted.

A big part of this would just be untangling a pile of code in SILGen for 
emitting function call arguments and applying them. Right now there’s too much 
duplication between method calls and property access and subscripts. I need to 
do some work in this area to implement default arguments for subscripts; I 
think this can be accomplished through some refactoring and deleting of code. I 
haven’t thought about throwing properties and subscripts but I imagine it would 
be similar.

Slava

> 
>> 
>> -- Ben
>> 
> 
> ___
> 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] Revisiting 'T != Type' in where clause

2017-03-16 Thread Slava Pestov via swift-evolution

> On Mar 16, 2017, at 8:36 PM, Jaden Geller  wrote:
> 
> 
>> On Mar 16, 2017, at 8:27 PM, Slava Pestov  wrote:
>> 
>> Overload resolution has a lot of heuristics, but it’s not magic. It simply 
>> doesn’t know how to handle this case.
>> 
>> I’d be in favor of consolidating and simplifying the overload resolution 
>> rules, with the goal of disambiguating common cases that are currently 
>> ambiguous. We might even be able to do that without breaking too much user 
>> code, since a lot of the rules there were put in place to handle specific 
>> situations that came up in the standard library.
> 
> Do you think there’s a simplification of the rules that would also better 
> handle most cases? I definitely found overload resolution to be confusing 
> topic when I first learned Swift (and still today tbh).

I’m as confused as you are. We don’t even have a good writeup of the existing 
rules anywhere.

Slava

> 
>> 
>> However adding more heuristics to handle specific examples is a -1 from me. 
>> :-)
>> 
>> Slava
>> 
>>> On Mar 16, 2017, at 7:38 PM, Jaden Geller via swift-evolution 
>>>  wrote:
>>> 
>>> I would’ve expected overload resolution to pick the “more specific” one in 
>>> this case without needing any additional constraints… 樂
>>> 
 On Mar 16, 2017, at 6:40 PM, Robert Bennett via swift-evolution 
  wrote:
 
 Hello,
 
 This discussion sort of fizzled out when the topic was first introduced. 
 Joe Groff had asked the following:
 
> Do you have a concrete example where you need this? It'd be good to know 
> whether the types are ambiguous due to type checker bugs, or whether 
> there's a principle by which they could be naturally ordered.
 
 There is an example of this ordering that I stumbled upon recently. 
 Suppose I wish to extend `Array` with a `uniques()` function that returns 
 an array containing the unique elements of `self`. For performance 
 reasons, I would first write a method for arrays with Hashable elements, 
 so that I could check for uniqueness in constant time per element.
 
 extension Array where Element: Hashable {
func uniques() -> [Element] {
var seen: Set = []
var uniq: [Element] = []

for e in self {
if !seen.contains(e) {
seen.insert(e)
uniq.append(e)
}
}

return uniq
}
 }
 
 However I would still like to have a `uniques()` method for arrays whose 
 elements are merely Equatable, and I'm willing to take the performance 
 cost of O(n) lookup per element.
 
 extension Array where Element: Equatable {
func uniques() -> [Element] {
var uniq: [Element] = []

for e in self {
if !uniq.contains(e) {
uniq.append(e)
}
}

return uniq
}
 }
 
 However, there is a problem, which is that elements that are Hashable are 
 also Equatable, and so there is ambiguity when calling this method:
 
 // error: ambiguous use of 'uniques()'
 print([1,2,3,1,2,4,5,1,2,3,4,5].uniques())
 
 
 If I could add `Element != Hashable` to the second extension, there would 
 be no ambiguity.
 
 FWIW replacing Array with Collection and Element with Iterator.Element 
 fixes the error. The first extension (the one for Hashables) is called. 
 I'm not sure why it is ambiguous in one case and not the other.
 
 ___
 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] Revisiting 'T != Type' in where clause

2017-03-16 Thread Jaden Geller via swift-evolution

> On Mar 16, 2017, at 8:27 PM, Slava Pestov  wrote:
> 
> Overload resolution has a lot of heuristics, but it’s not magic. It simply 
> doesn’t know how to handle this case.
> 
> I’d be in favor of consolidating and simplifying the overload resolution 
> rules, with the goal of disambiguating common cases that are currently 
> ambiguous. We might even be able to do that without breaking too much user 
> code, since a lot of the rules there were put in place to handle specific 
> situations that came up in the standard library.

Do you think there’s a simplification of the rules that would also better 
handle most cases? I definitely found overload resolution to be confusing topic 
when I first learned Swift (and still today tbh).

> 
> However adding more heuristics to handle specific examples is a -1 from me. 
> :-)
> 
> Slava
> 
>> On Mar 16, 2017, at 7:38 PM, Jaden Geller via swift-evolution 
>>  wrote:
>> 
>> I would’ve expected overload resolution to pick the “more specific” one in 
>> this case without needing any additional constraints… 樂
>> 
>>> On Mar 16, 2017, at 6:40 PM, Robert Bennett via swift-evolution 
>>>  wrote:
>>> 
>>> Hello,
>>> 
>>> This discussion sort of fizzled out when the topic was first introduced. 
>>> Joe Groff had asked the following:
>>> 
 Do you have a concrete example where you need this? It'd be good to know 
 whether the types are ambiguous due to type checker bugs, or whether 
 there's a principle by which they could be naturally ordered.
>>> 
>>> There is an example of this ordering that I stumbled upon recently. Suppose 
>>> I wish to extend `Array` with a `uniques()` function that returns an array 
>>> containing the unique elements of `self`. For performance reasons, I would 
>>> first write a method for arrays with Hashable elements, so that I could 
>>> check for uniqueness in constant time per element.
>>> 
>>> extension Array where Element: Hashable {
>>> func uniques() -> [Element] {
>>> var seen: Set = []
>>> var uniq: [Element] = []
>>> 
>>> for e in self {
>>> if !seen.contains(e) {
>>> seen.insert(e)
>>> uniq.append(e)
>>> }
>>> }
>>> 
>>> return uniq
>>> }
>>> }
>>> 
>>> However I would still like to have a `uniques()` method for arrays whose 
>>> elements are merely Equatable, and I'm willing to take the performance cost 
>>> of O(n) lookup per element.
>>> 
>>> extension Array where Element: Equatable {
>>> func uniques() -> [Element] {
>>> var uniq: [Element] = []
>>> 
>>> for e in self {
>>> if !uniq.contains(e) {
>>> uniq.append(e)
>>> }
>>> }
>>> 
>>> return uniq
>>> }
>>> }
>>> 
>>> However, there is a problem, which is that elements that are Hashable are 
>>> also Equatable, and so there is ambiguity when calling this method:
>>> 
>>> // error: ambiguous use of 'uniques()'
>>> print([1,2,3,1,2,4,5,1,2,3,4,5].uniques())
>>> 
>>> 
>>> If I could add `Element != Hashable` to the second extension, there would 
>>> be no ambiguity.
>>> 
>>> FWIW replacing Array with Collection and Element with Iterator.Element 
>>> fixes the error. The first extension (the one for Hashables) is called. I'm 
>>> not sure why it is ambiguous in one case and not the other.
>>> 
>>> ___
>>> 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] Revisiting 'T != Type' in where clause

2017-03-16 Thread Slava Pestov via swift-evolution

> On Mar 16, 2017, at 8:32 PM, Robert Bennett  wrote:
> 
> Agreed, I'm fine with a way of achieving this without T != Type. I suppose I 
> should have made the subject "Fix Swift's type checker in this particular 
> case".
> 
> I still have trouble figuring out *how* it can correctly handle ambiguity in 
> protocol extensions but be unable to in a "true" (constructible) type 
> extension. Does this warrant a bug report of some kind?

If you’re feeling adventurous, take a look at lib/Sema/CSRanking.cpp. It 
appears to have some special case logic for handling protocol extensions in 
particular.

Slava

> 
>> On Mar 16, 2017, at 11:27 PM, Slava Pestov  wrote:
>> 
>> Overload resolution has a lot of heuristics, but it’s not magic. It simply 
>> doesn’t know how to handle this case.
>> 
>> I’d be in favor of consolidating and simplifying the overload resolution 
>> rules, with the goal of disambiguating common cases that are currently 
>> ambiguous. We might even be able to do that without breaking too much user 
>> code, since a lot of the rules there were put in place to handle specific 
>> situations that came up in the standard library.
>> 
>> However adding more heuristics to handle specific examples is a -1 from me. 
>> :-)
>> 
>> Slava
>> 
>>> On Mar 16, 2017, at 7:38 PM, Jaden Geller via swift-evolution 
>>>  wrote:
>>> 
>>> I would’ve expected overload resolution to pick the “more specific” one in 
>>> this case without needing any additional constraints… 樂
>>> 
 On Mar 16, 2017, at 6:40 PM, Robert Bennett via swift-evolution 
  wrote:
 
 Hello,
 
 This discussion sort of fizzled out when the topic was first introduced. 
 Joe Groff had asked the following:
 
> Do you have a concrete example where you need this? It'd be good to know 
> whether the types are ambiguous due to type checker bugs, or whether 
> there's a principle by which they could be naturally ordered.
 
 There is an example of this ordering that I stumbled upon recently. 
 Suppose I wish to extend `Array` with a `uniques()` function that returns 
 an array containing the unique elements of `self`. For performance 
 reasons, I would first write a method for arrays with Hashable elements, 
 so that I could check for uniqueness in constant time per element.
 
 extension Array where Element: Hashable {
func uniques() -> [Element] {
var seen: Set = []
var uniq: [Element] = []

for e in self {
if !seen.contains(e) {
seen.insert(e)
uniq.append(e)
}
}

return uniq
}
 }
 
 However I would still like to have a `uniques()` method for arrays whose 
 elements are merely Equatable, and I'm willing to take the performance 
 cost of O(n) lookup per element.
 
 extension Array where Element: Equatable {
func uniques() -> [Element] {
var uniq: [Element] = []

for e in self {
if !uniq.contains(e) {
uniq.append(e)
}
}

return uniq
}
 }
 
 However, there is a problem, which is that elements that are Hashable are 
 also Equatable, and so there is ambiguity when calling this method:
 
 // error: ambiguous use of 'uniques()'
 print([1,2,3,1,2,4,5,1,2,3,4,5].uniques())
 
 
 If I could add `Element != Hashable` to the second extension, there would 
 be no ambiguity.
 
 FWIW replacing Array with Collection and Element with Iterator.Element 
 fixes the error. The first extension (the one for Hashables) is called. 
 I'm not sure why it is ambiguous in one case and not the other.
 
 ___
 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] Revisiting 'T != Type' in where clause

2017-03-16 Thread Robert Bennett via swift-evolution
Agreed, I'm fine with a way of achieving this without T != Type. I suppose I 
should have made the subject "Fix Swift's type checker in this particular case".

I still have trouble figuring out *how* it can correctly handle ambiguity in 
protocol extensions but be unable to in a "true" (constructible) type 
extension. Does this warrant a bug report of some kind?

> On Mar 16, 2017, at 11:27 PM, Slava Pestov  wrote:
> 
> Overload resolution has a lot of heuristics, but it’s not magic. It simply 
> doesn’t know how to handle this case.
> 
> I’d be in favor of consolidating and simplifying the overload resolution 
> rules, with the goal of disambiguating common cases that are currently 
> ambiguous. We might even be able to do that without breaking too much user 
> code, since a lot of the rules there were put in place to handle specific 
> situations that came up in the standard library.
> 
> However adding more heuristics to handle specific examples is a -1 from me. 
> :-)
> 
> Slava
> 
>> On Mar 16, 2017, at 7:38 PM, Jaden Geller via swift-evolution 
>>  wrote:
>> 
>> I would’ve expected overload resolution to pick the “more specific” one in 
>> this case without needing any additional constraints… 樂
>> 
>>> On Mar 16, 2017, at 6:40 PM, Robert Bennett via swift-evolution 
>>>  wrote:
>>> 
>>> Hello,
>>> 
>>> This discussion sort of fizzled out when the topic was first introduced. 
>>> Joe Groff had asked the following:
>>> 
 Do you have a concrete example where you need this? It'd be good to know 
 whether the types are ambiguous due to type checker bugs, or whether 
 there's a principle by which they could be naturally ordered.
>>> 
>>> There is an example of this ordering that I stumbled upon recently. Suppose 
>>> I wish to extend `Array` with a `uniques()` function that returns an array 
>>> containing the unique elements of `self`. For performance reasons, I would 
>>> first write a method for arrays with Hashable elements, so that I could 
>>> check for uniqueness in constant time per element.
>>> 
>>> extension Array where Element: Hashable {
>>> func uniques() -> [Element] {
>>> var seen: Set = []
>>> var uniq: [Element] = []
>>> 
>>> for e in self {
>>> if !seen.contains(e) {
>>> seen.insert(e)
>>> uniq.append(e)
>>> }
>>> }
>>> 
>>> return uniq
>>> }
>>> }
>>> 
>>> However I would still like to have a `uniques()` method for arrays whose 
>>> elements are merely Equatable, and I'm willing to take the performance cost 
>>> of O(n) lookup per element.
>>> 
>>> extension Array where Element: Equatable {
>>> func uniques() -> [Element] {
>>> var uniq: [Element] = []
>>> 
>>> for e in self {
>>> if !uniq.contains(e) {
>>> uniq.append(e)
>>> }
>>> }
>>> 
>>> return uniq
>>> }
>>> }
>>> 
>>> However, there is a problem, which is that elements that are Hashable are 
>>> also Equatable, and so there is ambiguity when calling this method:
>>> 
>>> // error: ambiguous use of 'uniques()'
>>> print([1,2,3,1,2,4,5,1,2,3,4,5].uniques())
>>> 
>>> 
>>> If I could add `Element != Hashable` to the second extension, there would 
>>> be no ambiguity.
>>> 
>>> FWIW replacing Array with Collection and Element with Iterator.Element 
>>> fixes the error. The first extension (the one for Hashables) is called. I'm 
>>> not sure why it is ambiguous in one case and not the other.
>>> 
>>> ___
>>> 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] Revisiting 'T != Type' in where clause

2017-03-16 Thread Slava Pestov via swift-evolution
Overload resolution has a lot of heuristics, but it’s not magic. It simply 
doesn’t know how to handle this case.

I’d be in favor of consolidating and simplifying the overload resolution rules, 
with the goal of disambiguating common cases that are currently ambiguous. We 
might even be able to do that without breaking too much user code, since a lot 
of the rules there were put in place to handle specific situations that came up 
in the standard library.

However adding more heuristics to handle specific examples is a -1 from me. :-)

Slava

> On Mar 16, 2017, at 7:38 PM, Jaden Geller via swift-evolution 
>  wrote:
> 
> I would’ve expected overload resolution to pick the “more specific” one in 
> this case without needing any additional constraints… 樂
> 
>> On Mar 16, 2017, at 6:40 PM, Robert Bennett via swift-evolution 
>>  wrote:
>> 
>> Hello,
>> 
>> This discussion sort of fizzled out when the topic was first introduced. Joe 
>> Groff had asked the following:
>> 
>>> Do you have a concrete example where you need this? It'd be good to know 
>>> whether the types are ambiguous due to type checker bugs, or whether 
>>> there's a principle by which they could be naturally ordered.
>> 
>> There is an example of this ordering that I stumbled upon recently. Suppose 
>> I wish to extend `Array` with a `uniques()` function that returns an array 
>> containing the unique elements of `self`. For performance reasons, I would 
>> first write a method for arrays with Hashable elements, so that I could 
>> check for uniqueness in constant time per element.
>> 
>> extension Array where Element: Hashable {
>>  func uniques() -> [Element] {
>>  var seen: Set = []
>>  var uniq: [Element] = []
>>  
>>  for e in self {
>>  if !seen.contains(e) {
>>  seen.insert(e)
>>  uniq.append(e)
>>  }
>>  }
>>  
>>  return uniq
>>  }
>> }
>> 
>> However I would still like to have a `uniques()` method for arrays whose 
>> elements are merely Equatable, and I'm willing to take the performance cost 
>> of O(n) lookup per element.
>> 
>> extension Array where Element: Equatable {
>>  func uniques() -> [Element] {
>>  var uniq: [Element] = []
>>  
>>  for e in self {
>>  if !uniq.contains(e) {
>>  uniq.append(e)
>>  }
>>  }
>>  
>>  return uniq
>>  }
>> }
>> 
>> However, there is a problem, which is that elements that are Hashable are 
>> also Equatable, and so there is ambiguity when calling this method:
>> 
>> // error: ambiguous use of 'uniques()'
>> print([1,2,3,1,2,4,5,1,2,3,4,5].uniques())
>> 
>> 
>> If I could add `Element != Hashable` to the second extension, there would be 
>> no ambiguity.
>> 
>> FWIW replacing Array with Collection and Element with Iterator.Element fixes 
>> the error. The first extension (the one for Hashables) is called. I'm not 
>> sure why it is ambiguous in one case and not the other.
>> 
>> ___
>> 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] Revisiting 'T != Type' in where clause

2017-03-16 Thread Jaden Geller via swift-evolution
I would’ve expected overload resolution to pick the “more specific” one in this 
case without needing any additional constraints… 樂

> On Mar 16, 2017, at 6:40 PM, Robert Bennett via swift-evolution 
>  wrote:
> 
> Hello,
> 
> This discussion sort of fizzled out when the topic was first introduced. Joe 
> Groff had asked the following:
> 
>> Do you have a concrete example where you need this? It'd be good to know 
>> whether the types are ambiguous due to type checker bugs, or whether there's 
>> a principle by which they could be naturally ordered.
> 
> There is an example of this ordering that I stumbled upon recently. Suppose I 
> wish to extend `Array` with a `uniques()` function that returns an array 
> containing the unique elements of `self`. For performance reasons, I would 
> first write a method for arrays with Hashable elements, so that I could check 
> for uniqueness in constant time per element.
> 
> extension Array where Element: Hashable {
>   func uniques() -> [Element] {
>   var seen: Set = []
>   var uniq: [Element] = []
>   
>   for e in self {
>   if !seen.contains(e) {
>   seen.insert(e)
>   uniq.append(e)
>   }
>   }
>   
>   return uniq
>   }
> }
> 
> However I would still like to have a `uniques()` method for arrays whose 
> elements are merely Equatable, and I'm willing to take the performance cost 
> of O(n) lookup per element.
> 
> extension Array where Element: Equatable {
>   func uniques() -> [Element] {
>   var uniq: [Element] = []
>   
>   for e in self {
>   if !uniq.contains(e) {
>   uniq.append(e)
>   }
>   }
>   
>   return uniq
>   }
> }
> 
> However, there is a problem, which is that elements that are Hashable are 
> also Equatable, and so there is ambiguity when calling this method:
> 
> // error: ambiguous use of 'uniques()'
> print([1,2,3,1,2,4,5,1,2,3,4,5].uniques())
> 
> 
> If I could add `Element != Hashable` to the second extension, there would be 
> no ambiguity.
> 
> FWIW replacing Array with Collection and Element with Iterator.Element fixes 
> the error. The first extension (the one for Hashables) is called. I'm not 
> sure why it is ambiguous in one case and not the other.
> 
> ___
> 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] Revisiting 'T != Type' in where clause

2017-03-16 Thread Robert Bennett via swift-evolution
Hello,

This discussion sort of fizzled out when the topic was first introduced. Joe 
Groff had asked the following:

> Do you have a concrete example where you need this? It'd be good to know 
> whether the types are ambiguous due to type checker bugs, or whether there's 
> a principle by which they could be naturally ordered.

There is an example of this ordering that I stumbled upon recently. Suppose I 
wish to extend `Array` with a `uniques()` function that returns an array 
containing the unique elements of `self`. For performance reasons, I would 
first write a method for arrays with Hashable elements, so that I could check 
for uniqueness in constant time per element.

extension Array where Element: Hashable {
func uniques() -> [Element] {
var seen: Set = []
var uniq: [Element] = []

for e in self {
if !seen.contains(e) {
seen.insert(e)
uniq.append(e)
}
}

return uniq
}
}

However I would still like to have a `uniques()` method for arrays whose 
elements are merely Equatable, and I'm willing to take the performance cost of 
O(n) lookup per element.

extension Array where Element: Equatable {
func uniques() -> [Element] {
var uniq: [Element] = []

for e in self {
if !uniq.contains(e) {
uniq.append(e)
}
}

return uniq
}
}

However, there is a problem, which is that elements that are Hashable are also 
Equatable, and so there is ambiguity when calling this method:

// error: ambiguous use of 'uniques()'
print([1,2,3,1,2,4,5,1,2,3,4,5].uniques())


If I could add `Element != Hashable` to the second extension, there would be no 
ambiguity.

FWIW replacing Array with Collection and Element with Iterator.Element fixes 
the error. The first extension (the one for Hashables) is called. I'm not sure 
why it is ambiguous in one case and not the other.

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


Re: [swift-evolution] [Proposal] Foundation Swift Encoders

2017-03-16 Thread Zach Waldowski via swift-evolution
> On Mar 16, 2017, at 4:18 PM, Itai Ferber  wrote:
> 
> Foundation’s common currency type for errors is unequivocally NSError, and 
> we’re not looking to change that as part of this proposal.
> 
Not in Swift, where it’s unequivocally Error, and errors thrown from Foundation 
bridge to CocoaError. Types that conform to Error can have custom bridges both 
to and from NSError. I didn’t suggest breaking up Foundation’s error types as 
part of this proposal, merely that while all this new code is being written, 
it’s a little backwards to tack on new home-brewed error codes to 
NSCocoaErrorDomain that don’t even exist in Objective-C.
> Reusing errors from the Cocoa domain has always been a reasonable choice for 
> 3rd-party developers, and we’d like to keep doing this.
> 
> We are looking to improve the experience of throwing such errors (with some 
> trivial extensions) by allowing you to do something like throw 
> CocoaError.error(.coderInvalidValue). (Of course, don’t quote me on the exact 
> syntax, as this is totally subject to change.)
> This is pretty simple, and nets you free user-facing localization.
> 
But, again, none of the three advantages mentioned here are exclusive to errors 
vended through NSError.

Zach Waldowski
z...@waldowski.me
> On 15 Mar 2017, at 22:46, Zach Waldowski wrote:
> 
> 
> Just a little one that came up with when thinking over the companion 
> proposal… see inline.
> 
>> On Mar 15, 2017, at 6:43 PM, Itai Ferber via swift-evolution 
>> > wrote:
>> Foundation-Provided Errors
>> 
>> Along with providing the above encoders and decoders, we would like to 
>> promote the use of a common set of error codes and messages across all new 
>> encoders and decoders. A common vocabulary of expected errors allows 
>> end-users to write code agnostic about the specific encoder/decoder 
>> implementation they are working with, whether first-party or third-party:
>> 
>> extension CocoaError.Code {
>> public static var coderInvalidValue: CocoaError.Code
>> public static var coderTypeMismatch: CocoaError.Code
>> public static var coderReadCorrupt: CocoaError.Code
>> public static var coderValueNotFound: CocoaError.Code
>> }
> 
> I find all the reasons compelling, but I don’t with the overall choice. A 
> common vocabulary, side table info, and localization can be achieved with a 
> dedicated error type for coders. I understand ABI (sorta) concerns are 
> involved here, that older Foundations will continue to return the same 
> NSError codes. However, it's never felt appropriate to create my own error 
> instances with NSCocoaErrorDomain, and this feels very similar to that. What 
> are our options here?
> 
> Zach Waldowski
> z...@waldowski.me 
> 

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


Re: [swift-evolution] [Proposal] Foundation Swift Encoders

2017-03-16 Thread Matthew Johnson via swift-evolution


Sent from my iPad

> On Mar 16, 2017, at 5:59 PM, Itai Ferber  wrote:
> 
> On 16 Mar 2017, at 15:45, Matthew Johnson wrote:
> 
> > On Mar 16, 2017, at 5:37 PM, Itai Ferber  wrote:
> 
> On 16 Mar 2017, at 14:48, Matthew Johnson wrote:
> 
> Thank you again for bringing these great proposals forward!
> 
> Thanks for reviewing it, and for your comments!
> 
> I only have a couple of questions about this proposal.
> 
> I noticed that the types in this proposal don’t conform to Encoder and 
> Decoder. Is the plan to have them to provide private conforming types to 
> Codable types they are asked to encode or decode?
> 
> Yes. This is because the top-level interface for encoding and decoding in 
> JSON and plist is different from the intermediate interface that Encoder and 
> Decoder offer. As such, the top-level types don’t conform to Encoder and 
> Decoder, but vend out internal types which do.
> This makes sense. I was initially concerned about the meaning of mutating 
> these values during encoding or decoding but it looks like that isn’t 
> possible without some really nefarious code that passes a reference to the 
> top-level encoder / decoder to an object that is getting encoded / decoded. 
> What will you do if somebody actually does this?
> 
> The options are copied immutably into the internal types and the originals 
> are not consulted during the process of encoding or decoding — we want to 
> prevent exactly this.
> FWIW, you can see the current implementation of this on the implementation PR.
> 
> Why are the strategy and format properties readwrite instead of configured at 
> initialization time? Is the intent that the encoder / decoder can be re-used 
> with a different configuration in a subsequent call to encode or decode?
> 
> Yes. It’s also a mouthful to have them all as params in the constructor, 
> especially if we add more options in the future.
> Taking them in an initializer would not need to be wordy - they could all 
> specify default arguments.
> 
> Sure, but if you want to specify a lot of them…
> But, this is more of a stylistic argument. Six of one, half-dozen of another. 
> The more useful thing is supporting mutation after initialization, which is a 
> reasonable thing to want to do.
> 
Fair enough.  This makes sense given the rest of the details.  I'm glad to hear 
you're copying them to the internal types when starting encoding / decoding!  :)
> Finally, I agree with Brent’s comments regarding errors. I would prefer to 
> see Foundation move away from NSError in favor of domain-specific error 
> types. That said, the comment that this is a broader discussion for 
> Foundation and not something to change in this proposal is reasonable. I hope 
> Foundation will consider changing this in the future.
> 
> Thanks for your understanding — we will keep these concerns in mind.
> 
> Matthew
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Foundation Swift Archival & Serialization

2017-03-16 Thread Matthew Johnson via swift-evolution


Sent from my iPad

> On Mar 16, 2017, at 5:54 PM, Ben Rimmington  wrote:
> 
> 
>>> On 16 Mar 2017, at 21:14, Matthew Johnson wrote:
>>> 
>>> On Mar 16, 2017, at 4:12 PM, Itai Ferber  wrote:
>>> 
>>> If throwing subscripts made it in the Swift 4 timeframe, then we would 
>>> certainly consider it.
>> 
>> Cool.  Any comment from the core team on whether this is a possibility?  If 
>> it is and nobody else wants to write a proposal I would be willing to do it.
> 
> "Throwing Properties and Subscripts" proposal by Brent Royal-Gordon (12 
> months ago):
> 
> 

Oh, great!  I had forgotten about this.  It would be awesome if we could revive 
this for Swift 4 especially so it can be considered as part of the interface of 
this API.  Even if Foundation doesn't adopt the, they would be a great 
complement for those of us who would prefer the lighter syntax and are willing 
to use our own wrapper.

> 
> -- Ben
> 

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


Re: [swift-evolution] [Proposal] Foundation Swift Encoders

2017-03-16 Thread Itai Ferber via swift-evolution



On 16 Mar 2017, at 15:45, Matthew Johnson wrote:


> On Mar 16, 2017, at 5:37 PM, Itai Ferber  wrote:


On 16 Mar 2017, at 14:48, Matthew Johnson wrote:

Thank you again for bringing these great proposals forward!

Thanks for reviewing it, and for your comments!

I only have a couple of questions about this proposal.

I noticed that the types in this proposal don’t conform to Encoder 
and Decoder. Is the plan to have them to provide private conforming 
types to Codable types they are asked to encode or decode?


Yes. This is because the top-level interface for encoding and 
decoding in JSON and plist is different from the intermediate 
interface that Encoder and Decoder offer. As such, the top-level 
types don’t conform to Encoder and Decoder, but vend out internal 
types which do.


This makes sense.  I was initially concerned about the meaning of 
mutating these values during encoding or decoding but it looks like 
that isn’t possible without some really nefarious code that passes a 
reference to the top-level encoder / decoder to an object that is 
getting encoded / decoded.  What will you do if somebody actually does 
this?
The options are copied immutably into the internal types and the 
originals are not consulted during the process of encoding or decoding 
— we want to prevent exactly this.
FWIW, you can see the current implementation of this on [the 
implementation PR](https://github.com/apple/swift/pull/8124).


Why are the strategy and format properties readwrite instead of 
configured at initialization time? Is the intent that the encoder / 
decoder can be re-used with a different configuration in a subsequent 
call to encode or decode?


Yes. It’s also a mouthful to have them all as params in the 
constructor, especially if we add more options in the future.


Taking them in an initializer would not need to be wordy - they could 
all specify default arguments.

Sure, but if you want to specify a lot of them…
But, this is more of a stylistic argument. Six of one, half-dozen of 
another. The more useful thing is supporting mutation after 
initialization, which is a reasonable thing to want to do.


Finally, I agree with Brent’s comments regarding errors. I would 
prefer to see Foundation move away from NSError in favor of 
domain-specific error types. That said, the comment that this is a 
broader discussion for Foundation and not something to change in this 
proposal is reasonable. I hope Foundation will consider changing this 
in the future.


Thanks for your understanding — we will keep these concerns in 
mind.


Matthew




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


Re: [swift-evolution] [Proposal] Foundation Swift Archival & Serialization

2017-03-16 Thread Ben Rimmington via swift-evolution

> On 16 Mar 2017, at 21:14, Matthew Johnson wrote:
> 
>> On Mar 16, 2017, at 4:12 PM, Itai Ferber  wrote:
>> 
>> If throwing subscripts made it in the Swift 4 timeframe, then we would 
>> certainly consider it.
> 
> Cool.  Any comment from the core team on whether this is a possibility?  If 
> it is and nobody else wants to write a proposal I would be willing to do it.

"Throwing Properties and Subscripts" proposal by Brent Royal-Gordon (12 months 
ago):



-- Ben

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


Re: [swift-evolution] [Proposal] Foundation Swift Encoders

2017-03-16 Thread Itai Ferber via swift-evolution
The sorted order of keys is an implementation detail of 
`PropertyListSerialization` which `JSONSerialization` does not share.
This would require a change in `JSONSerialization`, which is possible, 
but out of scope for this work specifically. It would have to go through 
review.


[FWIW, the key ordering isn’t changing at random; `JSONSerialization` 
writes keys in the order that it receives them (sorted in the order that 
`NSDictionary` stores them, based on hash). If you want this to not 
interfere with your Git repo (on a more immediate timescale), you can 
probably do something like adding a pre-commit Git hook to lint the file 
as needed. But I digress, this is totally off-topic.]


On 16 Mar 2017, at 14:57, Ben Rimmington wrote:

Sorry, I actually meant that keys would be ordered **alphabetically** 
(as they are with PropertyListSerialization).


I'm storing output from JSONSerialization in a git repository, and 
when I add/remove a single key-value the entire file changes, due to 
keys being reordered (seemingly at random).


-- Ben


Itai Ferber wrote:

By stable ordering, you mean dictionaries with keys being output in 
the order that they were encoded?
Potentially, but this would require additional work as neither Swift 
dictionaries nor NSMutableDictionary support this (reasonable seeing 
as dictionaries are by definition not sorted), and the current 
implementation uses JSONSerialization as the concrete serializer. 
Certainly not impossible, though.



On 16 Mar 2017, at 8:49, Ben Rimmington wrote:



Could the `JSONEncoder.OutputFormatting.prettyPrinted` case include 
the **stable ordering** of keys?


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


Re: [swift-evolution] [Proposal] Foundation Swift Encoders

2017-03-16 Thread Matthew Johnson via swift-evolution

> On Mar 16, 2017, at 5:37 PM, Itai Ferber  wrote:
> 
> On 16 Mar 2017, at 14:48, Matthew Johnson wrote:
> 
> Thank you again for bringing these great proposals forward!
> 
> Thanks for reviewing it, and for your comments!
> 
> I only have a couple of questions about this proposal.
> 
> I noticed that the types in this proposal don’t conform to Encoder and 
> Decoder. Is the plan to have them to provide private conforming types to 
> Codable types they are asked to encode or decode?
> 
> Yes. This is because the top-level interface for encoding and decoding in 
> JSON and plist is different from the intermediate interface that Encoder and 
> Decoder offer. As such, the top-level types don’t conform to Encoder and 
> Decoder, but vend out internal types which do.
> 
This makes sense.  I was initially concerned about the meaning of mutating 
these values during encoding or decoding but it looks like that isn’t possible 
without some really nefarious code that passes a reference to the top-level 
encoder / decoder to an object that is getting encoded / decoded.  What will 
you do if somebody actually does this?  
> Why are the strategy and format properties readwrite instead of configured at 
> initialization time? Is the intent that the encoder / decoder can be re-used 
> with a different configuration in a subsequent call to encode or decode?
> 
> Yes. It’s also a mouthful to have them all as params in the constructor, 
> especially if we add more options in the future.
> 
Taking them in an initializer would not need to be wordy - they could all 
specify default arguments.
> Finally, I agree with Brent’s comments regarding errors. I would prefer to 
> see Foundation move away from NSError in favor of domain-specific error 
> types. That said, the comment that this is a broader discussion for 
> Foundation and not something to change in this proposal is reasonable. I hope 
> Foundation will consider changing this in the future.
> 
> Thanks for your understanding — we will keep these concerns in mind.
> 
> Matthew
> 

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


Re: [swift-evolution] [Proposal] Foundation Swift Encoders

2017-03-16 Thread Itai Ferber via swift-evolution

On 16 Mar 2017, at 14:48, Matthew Johnson wrote:


Thank you again for bringing these great proposals forward!

Thanks for reviewing it, and for your comments!


I only have a couple of questions about this proposal.

I noticed that the types in this proposal don’t conform to Encoder 
and Decoder.  Is the plan to have them to provide private conforming 
types to Codable types they are asked to encode or decode?
Yes. This is because the top-level interface for encoding and decoding 
in JSON and plist is different from the intermediate interface that 
`Encoder` and `Decoder` offer. As such, the top-level types don’t 
conform to `Encoder` and `Decoder`, but vend out internal types which 
do.


Why are the strategy and format properties readwrite instead of 
configured at initialization time?  Is the intent that the encoder / 
decoder can be re-used with a different configuration in a subsequent 
call to encode or decode?
Yes. It’s also a mouthful to have them all as params in the 
constructor, especially if we add more options in the future.


Finally, I agree with Brent’s comments regarding errors.  I would 
prefer to see Foundation move away from NSError in favor of 
domain-specific error types.  That said, the comment that this is a 
broader discussion for Foundation and not something to change in this 
proposal is reasonable.  I hope Foundation will consider changing this 
in the future.

Thanks for your understanding — we will keep these concerns in mind.


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


Re: [swift-evolution] [Proposal] Foundation Swift Encoders

2017-03-16 Thread Ben Rimmington via swift-evolution
Sorry, I actually meant that keys would be ordered **alphabetically** (as they 
are with PropertyListSerialization).

I'm storing output from JSONSerialization in a git repository, and when I 
add/remove a single key-value the entire file changes, due to keys being 
reordered (seemingly at random).

-- Ben

> Itai Ferber wrote:
> 
> By stable ordering, you mean dictionaries with keys being output in the order 
> that they were encoded?
> Potentially, but this would require additional work as neither Swift 
> dictionaries nor NSMutableDictionary support this (reasonable seeing as 
> dictionaries are by definition not sorted), and the current implementation 
> uses JSONSerialization as the concrete serializer. Certainly not impossible, 
> though.
> 
>> On 16 Mar 2017, at 8:49, Ben Rimmington wrote:
>> 
>> 
>> 
>> Could the `JSONEncoder.OutputFormatting.prettyPrinted` case include the 
>> **stable ordering** of keys?
>> 
>> -- Ben
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Foundation Swift Encoders

2017-03-16 Thread Matthew Johnson via swift-evolution
Thank you again for bringing these great proposals forward!

I only have a couple of questions about this proposal.

I noticed that the types in this proposal don’t conform to Encoder and Decoder. 
 Is the plan to have them to provide private conforming types to Codable types 
they are asked to encode or decode?

Why are the strategy and format properties readwrite instead of configured at 
initialization time?  Is the intent that the encoder / decoder can be re-used 
with a different configuration in a subsequent call to encode or decode?

Finally, I agree with Brent’s comments regarding errors.  I would prefer to see 
Foundation move away from NSError in favor of domain-specific error types.  
That said, the comment that this is a broader discussion for Foundation and not 
something to change in this proposal is reasonable.  I hope Foundation will 
consider changing this in the future.

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


Re: [swift-evolution] Swift's reflection

2017-03-16 Thread Slava Pestov via swift-evolution
Adding write reflection to the existing Mirrors implementation should not be 
too difficult and we would accept a well-written PR that adds this capability.

Slava

> On Mar 15, 2017, at 8:10 AM, Dimitri Racordon via swift-evolution 
>  wrote:
> 
> Hello fellow evolutionists,
> 
> I’d like to ask if someone knows about the current state of affairs of the 
> evolution of the reflection API in Swift.
> I read it was (or at least used to be) in the scope of Swift 4 to improve on 
> the current capabilities, but failed to see any proposal in that direction 
> since then. I found this evolution post 
> (https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151214/003401.html
>  
> )
>  from quite a while ago, and would like to know if anything progressed since 
> then.
> 
> As a domain specific languages designer, reflection is an essential feature 
> for me. Unfortunately I think Swift is quite behind regarding that point. 
> Most specifically, the inability to set properties discovered from a mirror 
> (without resorting to the black magic of unsafe pointers) has a huge impact 
> on the simplicity of embedded DSLs.
> 
> Thanks,
> Dimitri Racordon
> 
> ___
> 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] Foundation Swift Archival & Serialization

2017-03-16 Thread Itai Ferber via swift-evolution



On 16 Mar 2017, at 13:27, David Hart wrote:

> On 16 Mar 2017, at 20:55, Itai Ferber via swift-evolution 
 wrote:


I’m going to reply to this thread as a whole — apologies if 
there’s someone’s comment that I’ve missed.


This is something that has come up in internal review, and we’ve 
certainly given it thought. As Zach has already mentioned, the 
primary concern with overloading based on return type is ambiguity.
There are many cases in which Swift’s type system currently does 
not handle ambiguity in the way that you would expect, and it can be 
very surprising. For instance,


func foo() -> Int { return 42 }
func foo() -> Double { return .pi }
func consumesInt(_ x : Int) { print(x) }

let x = foo() // Ambiguous use of foo()
consumesInt(x) // Even though x is going to be used as an Int
let y: Int = x // Same here
let x = foo() as Int works now, but it actually didn’t always — 
until a somewhat recent version of Swift AFAICT, the only way to 
resolve the ambiguity was through let x: Int = foo(). This has since 
been fixed, but it was very confusing to try to figure out the 
unambiguous way to call it.


Keep in mind that this isn’t an unreasonable thing to want to do:

struct Foo {
var x: Int
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: 
CodingKeys.self)


// Want to process an element before it’s assigned.
let x = container.decode(forKey: .x) // Ambiguous call

// Or whatever.
if x < 0 {
self.x = x + 100
else {
self.x = x * 200
}
}
}
You can write let x: Int = container.decode(…) or let x = 
container.decode(…) as Int, but this isn’t always intuitive.



That’s where I disagree. Let me try to prove my point:

You bring up the example of having to store the decoded value in a 
variable before setting it to a typed property. But its also not 
unreasonable to want to do the same thing when encoding the value, 
possibly storing it into a different type. If we follow that argument, 
its also not very intuitive to have to do


container.encode(x as Double, forKey: .x).

Wouldn’t that be an argument to have an API like this:

func encode(_ value: Data?, forKey key: Key, as type: T.Type) 
throws

I don’t agree that these are equivalent cases.

Here, for an `as` cast to be valid, the type of `x` must be an 
existential (I’m guessing `Any`).
The original `container.encode(x, forKey: .x)` call is not ambiguous 
because `x` has no type, but rather because the type of `x` does not 
match any of the overloads. You would get the same error as if you wrote


```swift
struct NonCodableFoo {}
let x = NonCodableFoo()
container.encode(x, forKey: .x)
```

You have to convert the type to something that fits one of the 
overloads.


On encode, there cannot be any true ambiguity because it’s not 
possible to satisfy more than one of these concrete overloads. You 
cannot have a thing with a type which would satisfy both, say, `Int` and 
`Double`.


I would argue that type inference is a core feature in Swift and that 
we should embrace it. I believe that in most cases the return value of 
encode will be stored into a typed property and type inference will do 
the right thing. In the few cases where the type has to be enforced, 
the patterns you mention above are not weird syntax; they are used and 
useful all over Swift:

Sure, but I think these cases are not equivalent.


let cgFloat: CGFloat = 42
42 has a default value of `Int`, but since `CGFloat` is 
`ExpressibleByIntLiteral`, this becomes the equivalent of writing `let 
cfFloat = CGFloat(42)`, which would not be ambiguous without the 
`CGFloat()`; you would just get an `Int`.


With `let x = container.decode(forKey: .x)`, has _has no type_ unless 
otherwise specified.



let pi = 3.14159265359 as Float
Same here, but with `Double` instead of `Int`, and `Float` instead of 
`CGFloat`…


let person = factory.get() // potential feature in Generics 
Manifesto
This isn’t type inference. This is type specification, which is 
exactly what we are trying to do. At the moment, explicit type 
specification has a different syntax: passing a metatype as an argument.


If this feature were available, this is what we would use.

The way I think about it is that the type argument is already there as 
a generic parameter. Adding an extra argument that needs to be 
explicitly given on every single call feels like unneeded verbosity to 
me.
For consideration: why does `let person = factory.get()` seem 
reasonable, but `let person = factory.get(Person.self)` does not?


Consider also that the metatype would also be necessary for 
decode(_ type: Value.Type, forKey: Key) -> Value 
because the return value of that certainly could be ambiguous in many 
cases.


Finally, the metatype arg allows you to express the following 
succinctly: let v: SuperClass = container.decode(SubClass.self, 
forKey: .v).


In the general case (decode) we 

Re: [swift-evolution] [Proposal] Foundation Swift Archival & Serialization

2017-03-16 Thread Matthew Johnson via swift-evolution
This is a fantastic proposal!  I am very much looking forward to robust 
Swift-native encoding and decoding in Foundation.  The compiler synthesized 
conformances is especially great!I want to thank everyone who worked on it. 
 It is clear that a lot of work went into the proposal.

The proposal covers a lot of ground so I’m breaking my comments up by topic in 
the order the occur in the proposal.

Encode / Decode only types:

Brent raised the question of decode only types.  Encode only types are also not 
uncommon when an API accepts an argument payload that gets serialized into the 
body of a request. The compiler synthesis feature in the proposal makes 
providing both encoding and decoding easy in common cases but this won’t always 
work as needed.

The obvious alternative is to have Decodable and Encodable protocols which 
Codable refines.  This would allow us to omit a conformance we don’t need when 
it can’t be synthesized.  

Your reply to Brent mentions using `fatalError` to avoid implementing the 
direction that isn't needed.  I think it would be better if the conformance can 
reflect what is actually supported by the type.  Requiring us to write 
`fatalError` as a stub for functionality we don’t need is a design problem IMO. 
 I don’t think the extra protocols are really that big a burden.  They don’t 
add any new functionality and are very easy to understand, especially 
considering the symmetry they would have with the other types you are 
introducing.

Coding Keys:

As others have mentioned, the design of this protocol does not require a value 
of a conforming type to actually be a valid key (it can return nil for both 
`intValue` and `stringValue`).  This seems problematic to me.

In the reply to Brent again you mention throwing and `preconditionFailure` as a 
way to handle incompatible keys.  This also seems problematic to me and feels 
like a design problem. If we really need to support more than one underlying 
key type and some encoders will reject some key types this information should 
be captured in the type system.  An encoder would only vend a keyed container 
for keys it actually supports.  Ideally the conformance of a type’s CodingKeys 
could be leveraged to produce a compiler error if an attempt was made to encode 
this type into an encoder that can’t support its keys.  In general, the idea is 
to produce static errors as close to the origin of the programming mistake as 
possible.  

I would very much prefer that we don’t defer to runtime assertions or thrown 
errors, etc for conditions that could be caught statically at compile time 
given the right design.  Other comments have indicated that static guarantees 
are important to the design (encoders *must* guarantee support of primitives 
specified by the protocols, etc).  Why is a static guarantee of compatible 
coding keys considered less important?

Keyed Containers:

Joe posted raised the topic of the alternative of using manual type erasure for 
the keyed containers rather than abstract classes.  Did you explore this 
direction at all?  It feels like a more natural approach for Swift and as Joe 
noted, it can be designed in such a way that eases migration to existentials in 
the future if that is the “ideal” design (which you mentioned in your response).

Decoding Containers:

returns: A value of the requested type, if present for the given key and 
convertible to the requested type.

Can you elaborate on the details of “convertible to the requested type” means?  
It think this is an important detail for the proposal.  

For example, I would expect numeric values to attempt conversion using the 
SE-0080 failable numeric conversion initializers (decoding JSON was a primary 
motivating use case for that proposal).  If the requested type conforms to 
RawRepresentable and the encoded value can be converted to RawValue (perhaps 
using a failable numeric initializer) I would expect the raw value initializer 
to be used to attempt conversion.  If Swift ever gained a standard mechanism 
for generalized value conversion I would also expect that to be used if a 
conversion is available from the encoded type to the requested type.

If either of those conversions fail I would expect something like an “invalid 
value” error or a “conversion failure” error rather than a “type mismatch” 
error.  The types don’t exactly mismatch, we just have a failable conversion 
process that did not succeed.

Context:

I’m glad Brent raised the topic of supporting multiple formats.  In his example 
the difference was remote and local formats.  I’ve also seen cases where the 
same API requires the same model to be encoded differently in different 
endpoints.  This is awful, but it also happens sometimes in the wild.  
Supporting an application specified encoding context would be very useful for 
handling these situations (the `codingKeyContex` would not always be sufficient 
and would usually not be a good way to determine the required encoding or 

Re: [swift-evolution] [Proposal] Foundation Swift Archival & Serialization

2017-03-16 Thread Matthew Johnson via swift-evolution

> On Mar 16, 2017, at 4:18 PM, Philippe Hausler  wrote:
> 
> One point of concern with making the implementations rely on that: it would 
> require any adopter of Codable to be built in swift 4 mode no? it might be 
> valuable to keep the protocol not requiring Swift 4 to aide in incremental 
> migration.

Yes, probably so.  I would be disappointed if we allowed the design of Swift 4 
features to be influenced by Swift 3.1 compatibility.

> 
>> On Mar 16, 2017, at 2:14 PM, Matthew Johnson via swift-evolution 
>> > wrote:
>> 
>> 
>>> On Mar 16, 2017, at 4:12 PM, Itai Ferber >> > wrote:
>>> 
>>> If throwing subscripts made it in the Swift 4 timeframe, then we would 
>>> certainly consider it.
>>> 
>> Cool.  Any comment from the core team on whether this is a possibility?  If 
>> it is and nobody else wants to write a proposal I would be willing to do it.
>>> On 16 Mar 2017, at 13:19, Matthew Johnson wrote:
>>> 
>>> 
 On Mar 16, 2017, at 3:01 PM, Itai Ferber > wrote:
 
 Subscripts, by the way, would not help here, since they cannot throw. 
 decode must be able to throw.
 SR-238 
 ;
  for Apple folks, 28775436.
 
>>> They don’t “help” but they do provide a more natural interface.  If the 
>>> Foundation team feels a more wordy interface is necessary that is ok.
>>> 
>>> I specifically mentioned that they can’t throw yet.  Throwing subscripts 
>>> would make a good companion proposal if they could fit into the Swift 4 
>>> timeframe.  If not, then yes we need a method rather than a subscript.  But 
>>> if we can get throwing subscripts into Swift 4, why not use Swift’s first 
>>> class syntactic support for keyed access to keyed containers?
>>> 
 On 16 Mar 2017, at 11:46, Matthew Johnson via swift-evolution wrote:
 
 
 
> On Mar 16, 2017, at 1:34 PM, Zach Waldowski via swift-evolution 
> > wrote:
> 
> On Thu, Mar 16, 2017, at 02:23 PM, Matthew Johnson via swift-evolution 
> wrote:
>> I don’t have an example but I don’t see a problem either.  There are two 
>> options for specifying the return type manually.  We can use the 
>> signature you used above and use `as` to specify the expected type:
>> 
>> let i = decode(.myKey) as Int
> 
> The awkwardness of this syntax is exactly what I'm referring to. Would a 
> beginner know to use "as Int" or ": Int"? Why would they? The 
> "prettiness" of the simple case doesn't make up for how difficult it is 
> to understand and fix its failure cases.
> 
> Any official Swift or Foundation API shouldn't, or shouldn't need to, 
> make use of "tricky" syntax.
 
 I don’t think this is especially tricky.  Nevertheless, we can avoid 
 requiring this syntax by moving the type argument to the end and providing 
 a default.  But I think return type inference is worth supporting.  It has 
 become widely adopted by the community already in this use case.
 
> 
>> If we don’t support this in Foundation we will continue to see 3rd party 
>> libraries that do this.
> 
> The proposal's been out for less than 24 hours, is it really productive 
> to already be taking our ball and go home over such a minor thing?
 
 I don’t think that’s what I’m doing at all.  This is a fantastic proposal. 
  I’m still working through it and writing up my more detailed thoughts.
 
 That said, as with many (most?) first drafts, there is room for 
 improvement.  I think it’s worth pointing out the syntax that many of us 
 would like to use for decoding and at least considering including it in 
 the proposal.  If the answer is that it’s trivial for those who want to 
 use subscripts to write the wrappers for return type inference and / or 
 subscripts themselves that’s ok.  But it’s a fair topic for discussion and 
 should at least be addressed as an alternative that was rejected for a 
 specific reason.
 
> 
> Zach Waldowski
> z...@waldowski.me 
> 
> 
> 
> 
> ___
> 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] Foundation Swift Archival & Serialization

2017-03-16 Thread Philippe Hausler via swift-evolution
One point of concern with making the implementations rely on that: it would 
require any adopter of Codable to be built in swift 4 mode no? it might be 
valuable to keep the protocol not requiring Swift 4 to aide in incremental 
migration.

> On Mar 16, 2017, at 2:14 PM, Matthew Johnson via swift-evolution 
>  wrote:
> 
> 
>> On Mar 16, 2017, at 4:12 PM, Itai Ferber > > wrote:
>> 
>> If throwing subscripts made it in the Swift 4 timeframe, then we would 
>> certainly consider it.
>> 
> Cool.  Any comment from the core team on whether this is a possibility?  If 
> it is and nobody else wants to write a proposal I would be willing to do it.
>> On 16 Mar 2017, at 13:19, Matthew Johnson wrote:
>> 
>> 
>>> On Mar 16, 2017, at 3:01 PM, Itai Ferber >> > wrote:
>>> 
>>> Subscripts, by the way, would not help here, since they cannot throw. 
>>> decode must be able to throw.
>>> SR-238 
>>> ;
>>>  for Apple folks, 28775436.
>>> 
>> They don’t “help” but they do provide a more natural interface.  If the 
>> Foundation team feels a more wordy interface is necessary that is ok.
>> 
>> I specifically mentioned that they can’t throw yet.  Throwing subscripts 
>> would make a good companion proposal if they could fit into the Swift 4 
>> timeframe.  If not, then yes we need a method rather than a subscript.  But 
>> if we can get throwing subscripts into Swift 4, why not use Swift’s first 
>> class syntactic support for keyed access to keyed containers?
>> 
>>> On 16 Mar 2017, at 11:46, Matthew Johnson via swift-evolution wrote:
>>> 
>>> 
>>> 
 On Mar 16, 2017, at 1:34 PM, Zach Waldowski via swift-evolution 
 > wrote:
 
 On Thu, Mar 16, 2017, at 02:23 PM, Matthew Johnson via swift-evolution 
 wrote:
> I don’t have an example but I don’t see a problem either.  There are two 
> options for specifying the return type manually.  We can use the 
> signature you used above and use `as` to specify the expected type:
> 
> let i = decode(.myKey) as Int
 
 The awkwardness of this syntax is exactly what I'm referring to. Would a 
 beginner know to use "as Int" or ": Int"? Why would they? The "prettiness" 
 of the simple case doesn't make up for how difficult it is to understand 
 and fix its failure cases.
 
 Any official Swift or Foundation API shouldn't, or shouldn't need to, make 
 use of "tricky" syntax.
>>> 
>>> I don’t think this is especially tricky.  Nevertheless, we can avoid 
>>> requiring this syntax by moving the type argument to the end and providing 
>>> a default.  But I think return type inference is worth supporting.  It has 
>>> become widely adopted by the community already in this use case.
>>> 
 
> If we don’t support this in Foundation we will continue to see 3rd party 
> libraries that do this.
 
 The proposal's been out for less than 24 hours, is it really productive to 
 already be taking our ball and go home over such a minor thing?
>>> 
>>> I don’t think that’s what I’m doing at all.  This is a fantastic proposal.  
>>> I’m still working through it and writing up my more detailed thoughts.
>>> 
>>> That said, as with many (most?) first drafts, there is room for 
>>> improvement.  I think it’s worth pointing out the syntax that many of us 
>>> would like to use for decoding and at least considering including it in the 
>>> proposal.  If the answer is that it’s trivial for those who want to use 
>>> subscripts to write the wrappers for return type inference and / or 
>>> subscripts themselves that’s ok.  But it’s a fair topic for discussion and 
>>> should at least be addressed as an alternative that was rejected for a 
>>> specific reason.
>>> 
 
 Zach Waldowski
 z...@waldowski.me 
 
 
 
 
 ___
 swift-evolution mailing list
 swift-evolution@swift.org 
 https://lists.swift.org/mailman/listinfo/swift-evolution 
 
>>> 
>>> ___
>>> swift-evolution mailing list
>>> swift-evolution@swift.org 
>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>> 
>> 
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

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


Re: [swift-evolution] [Proposal] Foundation Swift Archival & Serialization

2017-03-16 Thread Matthew Johnson via swift-evolution

> On Mar 16, 2017, at 4:12 PM, Itai Ferber  wrote:
> 
> If throwing subscripts made it in the Swift 4 timeframe, then we would 
> certainly consider it.
> 
Cool.  Any comment from the core team on whether this is a possibility?  If it 
is and nobody else wants to write a proposal I would be willing to do it.
> On 16 Mar 2017, at 13:19, Matthew Johnson wrote:
> 
> 
>> On Mar 16, 2017, at 3:01 PM, Itai Ferber > > wrote:
>> 
>> Subscripts, by the way, would not help here, since they cannot throw. decode 
>> must be able to throw.
>> SR-238 
>> ;
>>  for Apple folks, 28775436.
>> 
> They don’t “help” but they do provide a more natural interface.  If the 
> Foundation team feels a more wordy interface is necessary that is ok.
> 
> I specifically mentioned that they can’t throw yet.  Throwing subscripts 
> would make a good companion proposal if they could fit into the Swift 4 
> timeframe.  If not, then yes we need a method rather than a subscript.  But 
> if we can get throwing subscripts into Swift 4, why not use Swift’s first 
> class syntactic support for keyed access to keyed containers?
> 
>> On 16 Mar 2017, at 11:46, Matthew Johnson via swift-evolution wrote:
>> 
>> 
>> 
>>> On Mar 16, 2017, at 1:34 PM, Zach Waldowski via swift-evolution 
>>> > wrote:
>>> 
>>> On Thu, Mar 16, 2017, at 02:23 PM, Matthew Johnson via swift-evolution 
>>> wrote:
 I don’t have an example but I don’t see a problem either.  There are two 
 options for specifying the return type manually.  We can use the signature 
 you used above and use `as` to specify the expected type:
 
 let i = decode(.myKey) as Int
>>> 
>>> The awkwardness of this syntax is exactly what I'm referring to. Would a 
>>> beginner know to use "as Int" or ": Int"? Why would they? The "prettiness" 
>>> of the simple case doesn't make up for how difficult it is to understand 
>>> and fix its failure cases.
>>> 
>>> Any official Swift or Foundation API shouldn't, or shouldn't need to, make 
>>> use of "tricky" syntax.
>> 
>> I don’t think this is especially tricky.  Nevertheless, we can avoid 
>> requiring this syntax by moving the type argument to the end and providing a 
>> default.  But I think return type inference is worth supporting.  It has 
>> become widely adopted by the community already in this use case.
>> 
>>> 
 If we don’t support this in Foundation we will continue to see 3rd party 
 libraries that do this.
>>> 
>>> The proposal's been out for less than 24 hours, is it really productive to 
>>> already be taking our ball and go home over such a minor thing?
>> 
>> I don’t think that’s what I’m doing at all.  This is a fantastic proposal.  
>> I’m still working through it and writing up my more detailed thoughts.
>> 
>> That said, as with many (most?) first drafts, there is room for improvement. 
>>  I think it’s worth pointing out the syntax that many of us would like to 
>> use for decoding and at least considering including it in the proposal.  If 
>> the answer is that it’s trivial for those who want to use subscripts to 
>> write the wrappers for return type inference and / or subscripts themselves 
>> that’s ok.  But it’s a fair topic for discussion and should at least be 
>> addressed as an alternative that was rejected for a specific reason.
>> 
>>> 
>>> Zach Waldowski
>>> z...@waldowski.me 
>>> 
>>> 
>>> 
>>> 
>>> ___
>>> 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] Foundation Swift Archival & Serialization

2017-03-16 Thread Itai Ferber via swift-evolution
If throwing subscripts made it in the Swift 4 timeframe, then we would 
certainly consider it.


On 16 Mar 2017, at 13:19, Matthew Johnson wrote:


> On Mar 16, 2017, at 3:01 PM, Itai Ferber  wrote:


Subscripts, by the way, would not help here, since they cannot throw. 
decode must be able to throw.
SR-238 
; 
for Apple folks, 28775436.


They don’t “help” but they do provide a more natural interface.  
If the Foundation team feels a more wordy interface is necessary that 
is ok.


I specifically mentioned that they can’t throw yet.  Throwing 
subscripts would make a good companion proposal if they could fit into 
the Swift 4 timeframe.  If not, then yes we need a method rather than 
a subscript.  But if we can get throwing subscripts into Swift 4, why 
not use Swift’s first class syntactic support for keyed access to 
keyed containers?



On 16 Mar 2017, at 11:46, Matthew Johnson via swift-evolution wrote:



On Mar 16, 2017, at 1:34 PM, Zach Waldowski via swift-evolution 
> 
wrote:


On Thu, Mar 16, 2017, at 02:23 PM, Matthew Johnson via 
swift-evolution wrote:
I don’t have an example but I don’t see a problem either.  
There are two options for specifying the return type manually.  We 
can use the signature you used above and use `as` to specify the 
expected type:


let i = decode(.myKey) as Int


The awkwardness of this syntax is exactly what I'm referring to. 
Would a beginner know to use "as Int" or ": Int"? Why would they? 
The "prettiness" of the simple case doesn't make up for how 
difficult it is to understand and fix its failure cases.


Any official Swift or Foundation API shouldn't, or shouldn't need 
to, make use of "tricky" syntax.


I don’t think this is especially tricky.  Nevertheless, we can 
avoid requiring this syntax by moving the type argument to the end 
and providing a default.  But I think return type inference is worth 
supporting.  It has become widely adopted by the community already in 
this use case.




If we don’t support this in Foundation we will continue to see 
3rd party libraries that do this.


The proposal's been out for less than 24 hours, is it really 
productive to already be taking our ball and go home over such a 
minor thing?


I don’t think that’s what I’m doing at all.  This is a 
fantastic proposal.  I’m still working through it and writing up my 
more detailed thoughts.


That said, as with many (most?) first drafts, there is room for 
improvement.  I think it’s worth pointing out the syntax that many 
of us would like to use for decoding and at least considering 
including it in the proposal.  If the answer is that it’s trivial 
for those who want to use subscripts to write the wrappers for return 
type inference and / or subscripts themselves that’s ok.  But 
it’s a fair topic for discussion and should at least be addressed 
as an alternative that was rejected for a specific reason.




Zach Waldowski
z...@waldowski.me 




___
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] Foundation Swift Encoders

2017-03-16 Thread Itai Ferber via swift-evolution
By stable ordering, you mean dictionaries with keys being output in the 
order that they were encoded?
Potentially, but this would require additional work as neither Swift 
dictionaries nor `NSMutableDictionary` support this (reasonable seeing 
as dictionaries are by definition not sorted), and the current 
implementation uses `JSONSerialization` as the concrete serializer. 
Certainly not impossible, though.


On 16 Mar 2017, at 8:49, Ben Rimmington wrote:




Could the `JSONEncoder.OutputFormatting.prettyPrinted` case include 
the **stable ordering** of keys?


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


Re: [swift-evolution] [Proposal] Foundation Swift Archival & Serialization

2017-03-16 Thread Itai Ferber via swift-evolution

Hi Slava,

Thanks for your comments!

On 16 Mar 2017, at 13:50, Slava Pestov wrote:


Hi Itai,

I’m wondering what the motivation is for keeping this as part of 
Foundation and not the standard library. It seems like you’re 
landing an implementation of this in the Foundation overlay on master, 
and another copy of all the code will have to go into 
swift-corelibs-foundation. This seems suboptimal. Or are there future 
plans to unify the Foundation overlay with corelibs-foundation 
somehow?
This has to be part of Foundation because `Data`, a Foundation type, is 
one of the primitive types of serialization. This will be doubly true if 
we decide to add `Date` as another primitive type.


I agree that this is suboptimal at the moment, but we will work to find 
a way to keep the work in sync in a reasonable manner.


Also the implementation uses some Foundation-isms (NSMutableArray, 
NSNumber) and it would be nice to stick with idiomatic Swift as much 
as possible instead.

Using the Foundation framework is just as idiomatic in Swift… ;)
In this specific case, we need collections with reference semantics 
(`NSMutableArray` and `NSMutableDictionary`) and a concrete type-erased 
number box (`NSNumber`); theres’s no reason to reinvent the wheel if 
we already have exactly the tools we need.


The reference implementation at the moment goes through 
`JSONSerialization`, which affects the specifics of its implementation. 
This may change in the future.


Finally you should take a look at the integer protocol work 
(https://github.com/apple/swift-evolution/blob/master/proposals/0104-improved-integers.md 
) 
to replace the repetitive code surrounding primitive types, however I 
don’t know if this has landed in master yet.
As mentioned in other emails, the list of primitive types was carefully 
chosen because we need to have a concrete list of types which consumers 
can rely on being supported, and that `Encoder`s and `Decoder`s know 
they _must_ support.


Specifically:

1. For binary formats, the difference between an `Int16` and an `Int64` 
is significant. The `Encoder` would need to know that it’s received 
one type or another, not just a `FixedWidthInteger`; this would involve 
a runtime check of the concrete type of the argument
2. Any type can conform to these protocols — nothing is preventing me 
from writing an `Int37` type conforming to `FixedWidthInteger` and 
passing it in. Most encoders would really not know what to do with this 
type (especially ones with binary formats), but the failure would be a 
runtime one instead of a static one
  * A concrete example of this is the `FloatingPoint` protocol. 
`Float80` conforms to the protocol, but no common binary format I’ve 
seen supports 80-bit floating-point values. We’d prefer to prevent 
that statically by accepting only `Float` and `Double`
3. Consumers of the API then have no guarantees that a specific 
`Encoder` supports the type that they need. Did the encoder remember to 
support `UInt64` values? Similarly, `Encoder`s and `Decoder`s don’t 
know what types they need to be considering. Am I supposed to handle 
`UInt8` differently from `Int16`? With a list of concrete types, this 
becomes immediately clear — both consumers and writers of `Encoder`s 
have a clear contract.




Slava



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


Re: [swift-evolution] [Proposal] Foundation Swift Archival & Serialization

2017-03-16 Thread Tony Parker via swift-evolution
Hi Slava,

> On Mar 16, 2017, at 1:50 PM, Slava Pestov via swift-evolution 
>  wrote:
> 
> Hi Itai,
> 
> I’m wondering what the motivation is for keeping this as part of Foundation 
> and not the standard library. It seems like you’re landing an implementation 
> of this in the Foundation overlay on master, and another copy of all the code 
> will have to go into swift-corelibs-foundation. This seems suboptimal. Or are 
> there future plans to unify the Foundation overlay with corelibs-foundation 
> somehow?

I would like some unification in the future, but they are currently two 
separate implementations for a bunch of reasons (lack of bridging on Linux 
being a huge one, along with the inability of the standard library and runtime 
to distinguish between presence of Objective-C and the presence of Foundation).

> 
> Also the implementation uses some Foundation-isms (NSMutableArray, NSNumber) 
> and it would be nice to stick with idiomatic Swift as much as possible 
> instead.
> 

The implementation you’re looking at is for JSONArchiver, which is based on 
NSJSONSerialization, which is part of Foundation and not the standard library. 
That’s a primary reason to use Foundation. NSJSONSerialization also deals with 
types like ‘Date’ which are in Foundation. Finally, the primitive Coding API 
uses Data, which is a Foundation type.

So in summary, I’m fine with this API being part of Foundation. Foundation is 
available the same places the standard library is, so it is more than 
acceptable to use Foundation API and types here.

- Tony

> Finally you should take a look at the integer protocol work 
> (https://github.com/apple/swift-evolution/blob/master/proposals/0104-improved-integers.md
>  
> )
>  to replace the repetitive code surrounding primitive types, however I don’t 
> know if this has landed in master yet.
> 
> 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] [Proposal] Foundation Swift Encoders

2017-03-16 Thread Itai Ferber via swift-evolution



On 16 Mar 2017, at 1:00, Brent Royal-Gordon wrote:

On Mar 15, 2017, at 3:43 PM, Itai Ferber via swift-evolution 
 wrote:


Hi everyone,
This is a companion proposal to the Foundation Swift Archival & 
Serialization API. This introduces new encoders and decoders to be 
used as part of this system.

The proposal is available online and inlined below.


Executive summary: I like where you're going with this, but I'm 
worried about flexibility.


I'm not going to quote every bit of the JSON section because Apple 
Mail seems to destroy the formatting when I reply, but: I think you've 
identified several of the most important customization points (Date, 
Data, and illegal Floats). However, I think:


* People may want to map illegal Floats to legal floating-point values 
(say, `greatestFiniteMagnitude`, `-greatestFiniteMagnitude`, and `0`) 
or map them to `null`s. They may also want different behavior for 
different things: imagine `(positiveInfinity: 
Double.greatestFiniteMagnitude, negativeInfinity: 
-Double.greatestFiniteMagnitude, nan: .throw)`.

I agree, this may be something that users could want.



* Large integers are another big concern that you don't address. 
Because JSON only supports doubles, APIs that use 64-bit IDs often 
need them to be passed as strings, frequently with a different key 
("id_str" instead of "id").
This is not true — JSON has no limitations on what numbers it can 
represent. 340282366920938463463374607431768211455 (2^128-1) is a 
perfectly legitimate number in JSON, though you may have a hard reading 
it in on some platforms. _Javascript_ numbers are IEEE 754 doubles, but 
that’s a Javascript problem, not a JSON problem.


If what you mean here is that some large numbers should be encoded as 
strings instead of integers for the benefit of the other side reading it 
in a valid way, then perhaps.


* For that matter, style and capitalization are a problem. JSON style 
varies, but it *tends* to be snake_case, where Cocoa favors camelCase. 
You can address this at the CodingKey level by manually specifying 
string equivalents of all the coding keys, but that's kind of a pain, 
and it affects all of your code and all of your serializations.


I'm sorely tempted to suggest that we give the JSON encoder and 
decoder a delegate:


public protocol JSONCodingDelegate {
		/// Returns the string name to be used when encoding or decoding the 
given CodingKey as JSON.

///
/// - Returns: The string to use, or `nil` for the default.
		func jsonName(for key: CodingKey, at keyPath: [CodingKey], in 
encoderOrDecoder: AnyObject) throws -> String?


// These are used when encoding/decoding any of the integer 
types.
		func jsonValue(from integer: Int64, at keyPath: [CodingKey], in 
encoder: JSONEncoder) throws -> JSONValue?
		func integer(from jsonValue: JSONValue, at keyPath: [CodingKey], in 
decoder: JSONDecoder) throws -> Int64?


		// These are used when encoding/decoding any of the floating-point 
types.
		func jsonValue(from number: Double, at keyPath: [CodingKey], in 
encoder: JSONEncoder) throws -> JSONValue?
		func number(from jsonValue: JSONValue, at keyPath: [CodingKey], in 
decoder: JSONDecoder) throws -> Double?


// These are used when encoding/decoding Date.
		func jsonValue(from date: Date, at keyPath: [CodingKey], in encoder: 
JSONEncoder) throws -> JSONValue?
		func date(from jsonValue: JSONValue, at keyPath: [CodingKey], in 
decoder: JSONDecoder) throws -> Date?


// These are used when encoding/decoding Data.
		func jsonValue(from data: Data, at keyPath: [CodingKey], in encoder: 
JSONEncoder) throws -> JSONValue?
		func data(from jsonValue: JSONValue, at keyPath: [CodingKey], in 
decoder: JSONDecoder) throws -> Data?


		func jsonValue(from double: Double, at keyPath: [CodingKey], in 
encoder: JSONEncoder) throws -> JSONValue?
		func integer(from jsonValue: JSONValue, at keyPath: [CodingKey], in 
decoder: JSONDecoder) throws -> Double?

}
public enum JSONValue {
case string(String)
case number(Double)
case bool(Bool)
case object([String: JSONValue])
case array([JSONValue])
case null
}
I disagree with generalizing this to the point of being on a delegate. 
This is all work that you could be doing in `encode(to:)` and 
`decode(from:)`. In `encode(to:)`, it’s always possible to clamp an 
invalid floating-point number to `Double.greatestFiniteMagnitude`, and 
always possible to `encode("\(id)", forKey: .id)` instead of `encode(id, 
forKey: .id)`.


The options that we have on `JSONEncoder` and `JSONDecoder` straddle a 
fine line between being pedantically correct (and refusing to break 
encapsulation for encoded types), and being pragmatically useful. In 
theory, it certainly feels 

Re: [swift-evolution] [Proposal] Foundation Swift Archival & Serialization

2017-03-16 Thread Matthew Johnson via swift-evolution

> On Mar 16, 2017, at 3:27 PM, David Hart  wrote:
> 
> 
>> On 16 Mar 2017, at 20:55, Itai Ferber via swift-evolution 
>> > wrote:
>> 
>> I’m going to reply to this thread as a whole — apologies if there’s 
>> someone’s comment that I’ve missed.
>> 
>> This is something that has come up in internal review, and we’ve certainly 
>> given it thought. As Zach has already mentioned, the primary concern with 
>> overloading based on return type is ambiguity.
>> There are many cases in which Swift’s type system currently does not handle 
>> ambiguity in the way that you would expect, and it can be very surprising. 
>> For instance,
>> 
>> func foo() -> Int { return 42 }
>> func foo() -> Double { return .pi }
>> func consumesInt(_ x : Int) { print(x) }
>> 
>> let x = foo() // Ambiguous use of foo()
>> consumesInt(x) // Even though x is going to be used as an Int
>> let y: Int = x // Same here
>> let x = foo() as Int works now, but it actually didn’t always — until a 
>> somewhat recent version of Swift AFAICT, the only way to resolve the 
>> ambiguity was through let x: Int = foo(). This has since been fixed, but it 
>> was very confusing to try to figure out the unambiguous way to call it.
>> 
>> Keep in mind that this isn’t an unreasonable thing to want to do:
>> 
>> struct Foo {
>> var x: Int
>> init(from decoder: Decoder) throws {
>> let container = try decoder.container(keyedBy: CodingKeys.self)
>> 
>> // Want to process an element before it’s assigned.
>> let x = container.decode(forKey: .x) // Ambiguous call
>> 
>> // Or whatever.
>> if x < 0 {
>> self.x = x + 100
>> else {
>> self.x = x * 200
>> }
>> }
>> }
>> You can write let x: Int = container.decode(…) or let x = 
>> container.decode(…) as Int, but this isn’t always intuitive.
>> 
> That’s where I disagree. Let me try to prove my point:
> 
> You bring up the example of having to store the decoded value in a variable 
> before setting it to a typed property. But its also not unreasonable to want 
> to do the same thing when encoding the value, possibly storing it into a 
> different type. If we follow that argument, its also not very intuitive to 
> have to do
> 
> container.encode(x as Double, forKey: .x).
> 
> Wouldn’t that be an argument to have an API like this:
> 
> func encode(_ value: Data?, forKey key: Key, as type: T.Type) throws
> 
> I would argue that type inference is a core feature in Swift and that we 
> should embrace it. I believe that in most cases the return value of encode 
> will be stored into a typed property and type inference will do the right 
> thing. In the few cases where the type has to be enforced, the patterns you 
> mention above are not weird syntax; they are used and useful all over Swift:
> 
> let cgFloat: CGFloat = 42
> let pi = 3.14159265359 as Float
> let person = factory.get() // potential feature in Generics Manifesto
> 
> The way I think about it is that the type argument is already there as a 
> generic parameter. Adding an extra argument that needs to be explicitly given 
> on every single call feels like unneeded verbosity to me.

I agree with everything David says here.

>> Consider also that the metatype would also be necessary for decode> Codable>(_ type: Value.Type, forKey: Key) -> Value because the return value 
>> of that certainly could be ambiguous in many cases.
>> 
>> Finally, the metatype arg allows you to express the following succinctly: 
>> let v: SuperClass = container.decode(SubClass.self, forKey: .v).
>> 
>> In the general case (decode) we would need the metatype to 
>> avoid ambiguity. It’s not strictly necessary for primitive types, but helps 
>> in the case of ambiguity, and solves the conceptual overhead of "Why do I 
>> specify the type sometimes but not others? Why are some of these types 
>> special? Should I always provide the type? Why wouldn’t I?"
>> 
>> Matthew offered func decode(_ key: Key, as type: T.Type = T.self) throws 
>> -> T which looks appealing, but:
>> 
>> Doesn’t help resolve the ambiguity either
>> Allows for 3 ways of expressing the same thing (let x: Int = decode(key), 
>> let x = decode(key) as Int, and let x = decode(key, as: Int.self))
>> The cognitive overhead of figuring out all of the ambiguity goes away when 
>> we’re consistent everywhere.
>> FWIW, too, I am not convinced that Foundation should add API just because 
>> 3rd parties will add it.
>> 
> Agreed. Foundation should not add API just because 3rd parties do it. But 3rd 
> parties should not be dismissed entirely nonetheless. They are a good 
> breeding ground for ideas to spawn and shape Swift in interesting ways.

+1.  The point is not that we should do everything 3rd parties do.  But we 
should also not leave a gap in Foundation where the community has identified a 
lighter syntactic approach that has been used successfully in 

Re: [swift-evolution] [Proposal] Foundation Swift Archival & Serialization

2017-03-16 Thread Slava Pestov via swift-evolution
Hi Itai,

I’m wondering what the motivation is for keeping this as part of Foundation and 
not the standard library. It seems like you’re landing an implementation of 
this in the Foundation overlay on master, and another copy of all the code will 
have to go into swift-corelibs-foundation. This seems suboptimal. Or are there 
future plans to unify the Foundation overlay with corelibs-foundation somehow?

Also the implementation uses some Foundation-isms (NSMutableArray, NSNumber) 
and it would be nice to stick with idiomatic Swift as much as possible instead.

Finally you should take a look at the integer protocol work 
(https://github.com/apple/swift-evolution/blob/master/proposals/0104-improved-integers.md
 
)
 to replace the repetitive code surrounding primitive types, however I don’t 
know if this has landed in master yet.

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


Re: [swift-evolution] [Proposal] Foundation Swift Archival & Serialization

2017-03-16 Thread Matthew Johnson via swift-evolution

> On Mar 16, 2017, at 3:27 PM, Tony Parker  wrote:
> 
> 
>> On Mar 16, 2017, at 1:24 PM, Matthew Johnson via swift-evolution 
>> > wrote:
>> 
>>> 
>>> On Mar 16, 2017, at 2:58 PM, David Hart via swift-evolution 
>>> > wrote:
>>> 
>>> 
 On 16 Mar 2017, at 19:34, Zach Waldowski via swift-evolution 
 > wrote:
 
 On Thu, Mar 16, 2017, at 02:23 PM, Matthew Johnson via swift-evolution 
 wrote:
> I don’t have an example but I don’t see a problem either.  There are two 
> options for specifying the return type manually.  We can use the 
> signature you used above and use `as` to specify the expected type:
> 
> let i = decode(.myKey) as Int
 
 The awkwardness of this syntax is exactly what I'm referring to. Would a 
 beginner know to use "as Int" or ": Int"? Why would they? The "prettiness" 
 of the simple case doesn't make up for how difficult it is to understand 
 and fix its failure cases.
 
 Any official Swift or Foundation API shouldn't, or shouldn't need to, make 
 use of "tricky" syntax.
>>> 
>>> Two arguments:
>>> 
>>> 1) Most of the time, you will be setting the return value of decode into a 
>>> typed property and will not need ‘as’.
>>> 2) Even when you do need it, its not tricky syntax: it’s the official way 
>>> to direct the type inference engine in Swift.
>> 
>> +1 to both of David’s points.  Needing to explicitly resolve ambiguity 
>> during decoding is pretty rare.  When necessary the syntax is perfectly 
>> reasonable.  Swift users who don’t understand single statement inference 
>> works and how to guide the inference engine should learn about these topics 
>> sooner or later.  It won’t be a hard topic to search if a user runs into 
>> trouble either.  
>> 
>> Nevertheless, if the Foundation team is strongly opposed to this many of us 
>> will just write our own wrappers.  This isn’t hard but it makes Swift code 
>> less consistent throughout the community.  Supporting consistent usage 
>> throughout the community seems like a reasonable goal to me.  IMO that means 
>> not leaving obvious expressivity gaps that are easy to fill.  In this case, 
>> there is a very good reason why we prefer subscripts and return type 
>> inference.  It makes our code much more clear by omitting a bunch of 
>> needless and noisy words (which is one of the principles of the API Design 
>> Guidelines).
>> 
> 
> Hi Matthew,
> 
> While fully acknowledging that the proposed API adds some “wordiness", I 
> would also like to point out that the Swift API guidelines also explicitly 
> state a goal to avoid overloading on return type:
> 
> "Lastly, avoid “overloading on return type” because it causes ambiguities in 
> the presence of type inference.”

Fair enough.  I think that’s *usually* a great guideline.  However, in this 
specific use case I strongly support return type inference as a design that 
increases clarity while ambiguity is very rare in practice.  In any case, it 
sounds like the Foundation team has a pretty firm opinion on this topic.  I’ve 
offered my two cents and will let it drop now. :)

> 
> - Tony
> 
>>> David.
>>> 
> If we don’t support this in Foundation we will continue to see 3rd party 
> libraries that do this.
 
 The proposal's been out for less than 24 hours, is it really productive to 
 already be taking our ball and go home over such a minor thing?
 
 Zach Waldowski
 z...@waldowski.me 
 
 
 
 
 ___
 swift-evolution mailing list
 swift-evolution@swift.org 
 https://lists.swift.org/mailman/listinfo/swift-evolution 
 
>>> 
>>> ___
>>> swift-evolution mailing list
>>> swift-evolution@swift.org 
>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>> 
>> 
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org 
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> 

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


Re: [swift-evolution] [Proposal] Foundation Swift Archival & Serialization

2017-03-16 Thread David Hart via swift-evolution

> On 16 Mar 2017, at 20:55, Itai Ferber via swift-evolution 
>  wrote:
> 
> I’m going to reply to this thread as a whole — apologies if there’s someone’s 
> comment that I’ve missed.
> 
> This is something that has come up in internal review, and we’ve certainly 
> given it thought. As Zach has already mentioned, the primary concern with 
> overloading based on return type is ambiguity.
> There are many cases in which Swift’s type system currently does not handle 
> ambiguity in the way that you would expect, and it can be very surprising. 
> For instance,
> 
> func foo() -> Int { return 42 }
> func foo() -> Double { return .pi }
> func consumesInt(_ x : Int) { print(x) }
> 
> let x = foo() // Ambiguous use of foo()
> consumesInt(x) // Even though x is going to be used as an Int
> let y: Int = x // Same here
> let x = foo() as Int works now, but it actually didn’t always — until a 
> somewhat recent version of Swift AFAICT, the only way to resolve the 
> ambiguity was through let x: Int = foo(). This has since been fixed, but it 
> was very confusing to try to figure out the unambiguous way to call it.
> 
> Keep in mind that this isn’t an unreasonable thing to want to do:
> 
> struct Foo {
> var x: Int
> init(from decoder: Decoder) throws {
> let container = try decoder.container(keyedBy: CodingKeys.self)
> 
> // Want to process an element before it’s assigned.
> let x = container.decode(forKey: .x) // Ambiguous call
> 
> // Or whatever.
> if x < 0 {
> self.x = x + 100
> else {
> self.x = x * 200
> }
> }
> }
> You can write let x: Int = container.decode(…) or let x = container.decode(…) 
> as Int, but this isn’t always intuitive.
> 
That’s where I disagree. Let me try to prove my point:

You bring up the example of having to store the decoded value in a variable 
before setting it to a typed property. But its also not unreasonable to want to 
do the same thing when encoding the value, possibly storing it into a different 
type. If we follow that argument, its also not very intuitive to have to do

container.encode(x as Double, forKey: .x).

Wouldn’t that be an argument to have an API like this:

func encode(_ value: Data?, forKey key: Key, as type: T.Type) throws

I would argue that type inference is a core feature in Swift and that we should 
embrace it. I believe that in most cases the return value of encode will be 
stored into a typed property and type inference will do the right thing. In the 
few cases where the type has to be enforced, the patterns you mention above are 
not weird syntax; they are used and useful all over Swift:

let cgFloat: CGFloat = 42
let pi = 3.14159265359 as Float
let person = factory.get() // potential feature in Generics Manifesto

The way I think about it is that the type argument is already there as a 
generic parameter. Adding an extra argument that needs to be explicitly given 
on every single call feels like unneeded verbosity to me.
> Consider also that the metatype would also be necessary for decode Codable>(_ type: Value.Type, forKey: Key) -> Value because the return value 
> of that certainly could be ambiguous in many cases.
> 
> Finally, the metatype arg allows you to express the following succinctly: let 
> v: SuperClass = container.decode(SubClass.self, forKey: .v).
> 
> In the general case (decode) we would need the metatype to 
> avoid ambiguity. It’s not strictly necessary for primitive types, but helps 
> in the case of ambiguity, and solves the conceptual overhead of "Why do I 
> specify the type sometimes but not others? Why are some of these types 
> special? Should I always provide the type? Why wouldn’t I?"
> 
> Matthew offered func decode(_ key: Key, as type: T.Type = T.self) throws 
> -> T which looks appealing, but:
> 
> Doesn’t help resolve the ambiguity either
> Allows for 3 ways of expressing the same thing (let x: Int = decode(key), let 
> x = decode(key) as Int, and let x = decode(key, as: Int.self))
> The cognitive overhead of figuring out all of the ambiguity goes away when 
> we’re consistent everywhere.
> FWIW, too, I am not convinced that Foundation should add API just because 3rd 
> parties will add it.
> 
Agreed. Foundation should not add API just because 3rd parties do it. But 3rd 
parties should not be dismissed entirely nonetheless. They are a good breeding 
ground for ideas to spawn and shape Swift in interesting ways.
> The ambiguity in the general case cannot be solved by wrappers, and I would 
> prefer to provide one simple, consistent solution; if 3rd parties would like 
> to add wrappers for their own sake, then I certainly encourage that.
> 
> On 16 Mar 2017, at 11:46, Matthew Johnson via swift-evolution wrote:
> 
> 
> 
>> On Mar 16, 2017, at 1:34 PM, Zach Waldowski via swift-evolution 
>> > wrote:
>> 
>> On Thu, Mar 16, 2017, at 02:23 PM, Matthew 

Re: [swift-evolution] [Proposal] Foundation Swift Archival & Serialization

2017-03-16 Thread Tony Parker via swift-evolution

> On Mar 16, 2017, at 1:24 PM, Matthew Johnson via swift-evolution 
>  wrote:
> 
>> 
>> On Mar 16, 2017, at 2:58 PM, David Hart via swift-evolution 
>> > wrote:
>> 
>> 
>>> On 16 Mar 2017, at 19:34, Zach Waldowski via swift-evolution 
>>> > wrote:
>>> 
>>> On Thu, Mar 16, 2017, at 02:23 PM, Matthew Johnson via swift-evolution 
>>> wrote:
 I don’t have an example but I don’t see a problem either.  There are two 
 options for specifying the return type manually.  We can use the signature 
 you used above and use `as` to specify the expected type:
 
 let i = decode(.myKey) as Int
>>> 
>>> The awkwardness of this syntax is exactly what I'm referring to. Would a 
>>> beginner know to use "as Int" or ": Int"? Why would they? The "prettiness" 
>>> of the simple case doesn't make up for how difficult it is to understand 
>>> and fix its failure cases.
>>> 
>>> Any official Swift or Foundation API shouldn't, or shouldn't need to, make 
>>> use of "tricky" syntax.
>> 
>> Two arguments:
>> 
>> 1) Most of the time, you will be setting the return value of decode into a 
>> typed property and will not need ‘as’.
>> 2) Even when you do need it, its not tricky syntax: it’s the official way to 
>> direct the type inference engine in Swift.
> 
> +1 to both of David’s points.  Needing to explicitly resolve ambiguity during 
> decoding is pretty rare.  When necessary the syntax is perfectly reasonable.  
> Swift users who don’t understand single statement inference works and how to 
> guide the inference engine should learn about these topics sooner or later.  
> It won’t be a hard topic to search if a user runs into trouble either.  
> 
> Nevertheless, if the Foundation team is strongly opposed to this many of us 
> will just write our own wrappers.  This isn’t hard but it makes Swift code 
> less consistent throughout the community.  Supporting consistent usage 
> throughout the community seems like a reasonable goal to me.  IMO that means 
> not leaving obvious expressivity gaps that are easy to fill.  In this case, 
> there is a very good reason why we prefer subscripts and return type 
> inference.  It makes our code much more clear by omitting a bunch of needless 
> and noisy words (which is one of the principles of the API Design Guidelines).
> 

Hi Matthew,

While fully acknowledging that the proposed API adds some “wordiness", I would 
also like to point out that the Swift API guidelines also explicitly state a 
goal to avoid overloading on return type:

"Lastly, avoid “overloading on return type” because it causes ambiguities in 
the presence of type inference.”

- Tony

>> David.
>> 
 If we don’t support this in Foundation we will continue to see 3rd party 
 libraries that do this.
>>> 
>>> The proposal's been out for less than 24 hours, is it really productive to 
>>> already be taking our ball and go home over such a minor thing?
>>> 
>>> Zach Waldowski
>>> z...@waldowski.me 
>>> 
>>> 
>>> 
>>> 
>>> ___
>>> swift-evolution mailing list
>>> swift-evolution@swift.org 
>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>> 
>> 
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org 
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org 
> https://lists.swift.org/mailman/listinfo/swift-evolution 
> 
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Foundation Swift Archival & Serialization

2017-03-16 Thread Matthew Johnson via swift-evolution

> On Mar 16, 2017, at 2:58 PM, David Hart via swift-evolution 
>  wrote:
> 
> 
>> On 16 Mar 2017, at 19:34, Zach Waldowski via swift-evolution 
>> > wrote:
>> 
>> On Thu, Mar 16, 2017, at 02:23 PM, Matthew Johnson via swift-evolution wrote:
>>> I don’t have an example but I don’t see a problem either.  There are two 
>>> options for specifying the return type manually.  We can use the signature 
>>> you used above and use `as` to specify the expected type:
>>> 
>>> let i = decode(.myKey) as Int
>> 
>> The awkwardness of this syntax is exactly what I'm referring to. Would a 
>> beginner know to use "as Int" or ": Int"? Why would they? The "prettiness" 
>> of the simple case doesn't make up for how difficult it is to understand and 
>> fix its failure cases.
>> 
>> Any official Swift or Foundation API shouldn't, or shouldn't need to, make 
>> use of "tricky" syntax.
> 
> Two arguments:
> 
> 1) Most of the time, you will be setting the return value of decode into a 
> typed property and will not need ‘as’.
> 2) Even when you do need it, its not tricky syntax: it’s the official way to 
> direct the type inference engine in Swift.

+1 to both of David’s points.  Needing to explicitly resolve ambiguity during 
decoding is pretty rare.  When necessary the syntax is perfectly reasonable.  
Swift users who don’t understand single statement inference works and how to 
guide the inference engine should learn about these topics sooner or later.  It 
won’t be a hard topic to search if a user runs into trouble either.  

Nevertheless, if the Foundation team is strongly opposed to this many of us 
will just write our own wrappers.  This isn’t hard but it makes Swift code less 
consistent throughout the community.  Supporting consistent usage throughout 
the community seems like a reasonable goal to me.  IMO that means not leaving 
obvious expressivity gaps that are easy to fill.  In this case, there is a very 
good reason why we prefer subscripts and return type inference.  It makes our 
code much more clear by omitting a bunch of needless and noisy words (which is 
one of the principles of the API Design Guidelines).

> 
> David.
> 
>>> If we don’t support this in Foundation we will continue to see 3rd party 
>>> libraries that do this.
>> 
>> The proposal's been out for less than 24 hours, is it really productive to 
>> already be taking our ball and go home over such a minor thing?
>> 
>> Zach Waldowski
>> z...@waldowski.me 
>> 
>> 
>> 
>> 
>> ___
>> 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] Foundation Swift Archival & Serialization

2017-03-16 Thread Matthew Johnson via swift-evolution

> On Mar 16, 2017, at 3:01 PM, Itai Ferber  wrote:
> 
> Subscripts, by the way, would not help here, since they cannot throw. decode 
> must be able to throw.
> SR-238 
> ;
>  for Apple folks, 28775436.
> 
They don’t “help” but they do provide a more natural interface.  If the 
Foundation team feels a more wordy interface is necessary that is ok.

I specifically mentioned that they can’t throw yet.  Throwing subscripts would 
make a good companion proposal if they could fit into the Swift 4 timeframe.  
If not, then yes we need a method rather than a subscript.  But if we can get 
throwing subscripts into Swift 4, why not use Swift’s first class syntactic 
support for keyed access to keyed containers?

> On 16 Mar 2017, at 11:46, Matthew Johnson via swift-evolution wrote:
> 
> 
> 
>> On Mar 16, 2017, at 1:34 PM, Zach Waldowski via swift-evolution 
>> > wrote:
>> 
>> On Thu, Mar 16, 2017, at 02:23 PM, Matthew Johnson via swift-evolution wrote:
>>> I don’t have an example but I don’t see a problem either.  There are two 
>>> options for specifying the return type manually.  We can use the signature 
>>> you used above and use `as` to specify the expected type:
>>> 
>>> let i = decode(.myKey) as Int
>> 
>> The awkwardness of this syntax is exactly what I'm referring to. Would a 
>> beginner know to use "as Int" or ": Int"? Why would they? The "prettiness" 
>> of the simple case doesn't make up for how difficult it is to understand and 
>> fix its failure cases.
>> 
>> Any official Swift or Foundation API shouldn't, or shouldn't need to, make 
>> use of "tricky" syntax.
> 
> I don’t think this is especially tricky.  Nevertheless, we can avoid 
> requiring this syntax by moving the type argument to the end and providing a 
> default.  But I think return type inference is worth supporting.  It has 
> become widely adopted by the community already in this use case.
> 
>> 
>>> If we don’t support this in Foundation we will continue to see 3rd party 
>>> libraries that do this.
>> 
>> The proposal's been out for less than 24 hours, is it really productive to 
>> already be taking our ball and go home over such a minor thing?
> 
> I don’t think that’s what I’m doing at all.  This is a fantastic proposal.  
> I’m still working through it and writing up my more detailed thoughts.
> 
> That said, as with many (most?) first drafts, there is room for improvement.  
> I think it’s worth pointing out the syntax that many of us would like to use 
> for decoding and at least considering including it in the proposal.  If the 
> answer is that it’s trivial for those who want to use subscripts to write the 
> wrappers for return type inference and / or subscripts themselves that’s ok.  
> But it’s a fair topic for discussion and should at least be addressed as an 
> alternative that was rejected for a specific reason.
> 
>> 
>> Zach Waldowski
>> z...@waldowski.me 
>> 
>> 
>> 
>> 
>> ___
>> 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] Foundation Swift Encoders

2017-03-16 Thread Itai Ferber via swift-evolution

We’ll keep this in mind. :)

On 15 Mar 2017, at 19:58, Will Stanton wrote:


Hello Itai,

Thanks for your response and its explanations!

Agreed that comprehension of multiple formats is important since there 
are a couple common ways of encoding JSON dates!


Still, ISO 8601 appears pretty often (though I don’t have data on 
that, Stack Overflow says RFC 7493 I-JSON prefers ISO 8601; 
https://tools.ietf.org/html/rfc7493#section-4.3), and as other servers 
might make/handle a lot of JSON produced to/from the API, I think it 
would be disadvantageous to default to `deferredToDate` (if 
`deferredToDate` doesn't use the ISO 8601 format).


As you mention, writers/readers have to agree on their format - my 2¢ 
is that ISO 8601 would be more common, and so a better default, than a 
Unix or reference date timestamp.


Regards,
Will Stanton


-—Gracias for the prediction :-)




On Mar 15, 2017, at 9:53 PM, Itai Ferber  wrote:

Hi Will,

Thanks for your comments!
deferredToDate simply uses the default implementation that Date 
provides — since it is not a primitive type like Int or String and 
conforms to Codable itself, it will have an implementation of 
init(from:) and encode(to:). It will have an implementation that 
makes sense for Date in general, but since a big use-case for JSON 
lies in talking to external servers which you don't control, allowing 
for custom date formatting is important.


To that end, although ISO 8601 may make sense for some applications 
as the default, it is less efficient to format, encode, decode, and 
parse than, say, writing out a UNIX timestamp as a Double (or 
similar). Thus, the default is to allow Date to pick a representation 
that best suits itself, and if you need customization, you have the 
option to use it.


Since Date makes a concrete decision about how to encode, both sides 
will need to use deferredToDate for compatibility, in the same way 
that they would have to agree about ISO 8601, or any of the other 
options.


HTH!

— Itai

P.S. About Xcode autocompletion slowdown, I don't know to be honest, 
but I can't imagine it would be significant. Only certain types have 
enc... or dec... and even then, the list of methods isn't that long.
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Foundation Swift Encoders

2017-03-16 Thread Itai Ferber via swift-evolution
Foundation’s common currency type for errors is unequivocally 
`NSError`, and we’re not looking to change that as part of this 
proposal.
Reusing errors from the Cocoa domain has always been a reasonable choice 
for 3rd-party developers, and we’d like to keep doing this.


We are looking to improve the experience of throwing such errors (with 
some trivial extensions) by allowing you to do something like `throw 
CocoaError.error(.coderInvalidValue)`. (Of course, don’t quote me on 
the exact syntax, as this is totally subject to change.)

This is pretty simple, and nets you free user-facing localization.

On 15 Mar 2017, at 22:46, Zach Waldowski wrote:

Just a little one that came up with when thinking over the companion 
proposal… see inline.


On Mar 15, 2017, at 6:43 PM, Itai Ferber via swift-evolution 
 wrote:

Foundation-Provided Errors

Along with providing the above encoders and decoders, we would like 
to promote the use of a common set of error codes and messages across 
all new encoders and decoders. A common vocabulary of expected errors 
allows end-users to write code agnostic about the specific 
encoder/decoder implementation they are working with, whether 
first-party or third-party:


extension CocoaError.Code {
public static var coderInvalidValue: CocoaError.Code
public static var coderTypeMismatch: CocoaError.Code
public static var coderReadCorrupt: CocoaError.Code
public static var coderValueNotFound: CocoaError.Code
}


I find all the reasons compelling, but I don’t with the overall 
choice. A common vocabulary, side table info, and localization can be 
achieved with a dedicated error type for coders. I understand ABI 
(sorta) concerns are involved here, that older Foundations will 
continue to return the same NSError codes. However, it's never felt 
appropriate to create my own error instances with NSCocoaErrorDomain, 
and this feels very similar to that. What are our options here?


Zach Waldowski
z...@waldowski.me



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


Re: [swift-evolution] [Proposal] Foundation Swift Archival & Serialization

2017-03-16 Thread Itai Ferber via swift-evolution

Thanks for the comments, David.
I responded to #2 in a separate email, but wanted to get back to 
responding to #1.


In implementing this, I have had the same thoughts. Ideally, one day, we 
would be able to migrate the implementation of this away from the 
compiler to public API (through reflection, property behaviors, or 
similar). If the compiler offers external features that would allow us 
to do everything that we want, I would be more than happy to move the 
implementation from inside the compiler to outside of it.


On 16 Mar 2017, at 0:09, David Hart wrote:


First of all, great proposal :D

Brent, earlier in the thread makes a lot of good points. But I’d 
still like to discuss two subjects:


1) What makes the proposal really stand on its feet compared to 
third-party libraries is the compiler generation magic. I feel divided 
about it. On one hand, this is the only solution today to have this 
level of type and key safety. But on another hand, I have the 
impression that future versions of Swift (with more reflection, 
property behaviours, lenses, etc…) would dramatically affect how 
this subject is treated and implemented. Are you worried that we are 
asking the compiler to do work which might be un-necessary in the 
future? That this topic would be better expressed with more powerful 
language features? Any plans to migrate for this API to smoothly 
migrate to those features in the future?


2) Libraries like Marshal (https://github.com/utahiosmac/Marshal 
) and Unbox 
(https://github.com/JohnSundell/Unbox 
) don’t require the decoding 
functions to provide the type: those functions are generic on the 
return turn and it’s automatically inferred:


func decode(key: Key) -> T

self.stringProperty = decode(key: .stringProperty) // correct 
specialisation of the generic function chosen by the compiler


Is there a reason the proposal did not choose this solution? Its quite 
sweet.



Swift Archival & Serialization
Proposal: SE- 
Author(s): Itai Ferber , Michael LeHew 
, Tony Parker 

Review Manager: TBD
Status: Awaiting review
Associated PRs:
#8124 
#8125 



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


Re: [swift-evolution] [Proposal] Foundation Swift Archival & Serialization

2017-03-16 Thread Itai Ferber via swift-evolution
Subscripts, by the way, would not help here, since they cannot throw. 
`decode` must be able to throw.
[SR-238](https://bugs.swift.org/browse/SR-238?jql=text%20~%20%22subscript%20throw%22); 
for Apple folks, 28775436.


On 16 Mar 2017, at 11:46, Matthew Johnson via swift-evolution wrote:

> On Mar 16, 2017, at 1:34 PM, Zach Waldowski via swift-evolution 
 wrote:


On Thu, Mar 16, 2017, at 02:23 PM, Matthew Johnson via 
swift-evolution wrote:
I don’t have an example but I don’t see a problem either.  There 
are two options for specifying the return type manually.  We can use 
the signature you used above and use `as` to specify the expected 
type:


let i = decode(.myKey) as Int


The awkwardness of this syntax is exactly what I'm referring to. 
Would a beginner know to use "as Int" or ": Int"? Why would they? The 
"prettiness" of the simple case doesn't make up for how difficult it 
is to understand and fix its failure cases.


Any official Swift or Foundation API shouldn't, or shouldn't need to, 
make use of "tricky" syntax.


I don’t think this is especially tricky.  Nevertheless, we can avoid 
requiring this syntax by moving the type argument to the end and 
providing a default.  But I think return type inference is worth 
supporting.  It has become widely adopted by the community already in 
this use case.




If we don’t support this in Foundation we will continue to see 3rd 
party libraries that do this.


The proposal's been out for less than 24 hours, is it really 
productive to already be taking our ball and go home over such a 
minor thing?


I don’t think that’s what I’m doing at all.  This is a fantastic 
proposal.  I’m still working through it and writing up my more 
detailed thoughts.


That said, as with many (most?) first drafts, there is room for 
improvement.  I think it’s worth pointing out the syntax that many 
of us would like to use for decoding and at least considering 
including it in the proposal.  If the answer is that it’s trivial 
for those who want to use subscripts to write the wrappers for return 
type inference and / or subscripts themselves that’s ok.  But it’s 
a fair topic for discussion and should at least be addressed as an 
alternative that was rejected for a specific reason.




Zach Waldowski
z...@waldowski.me 




___
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] Foundation Swift Archival & Serialization

2017-03-16 Thread David Hart via swift-evolution

> On 16 Mar 2017, at 19:34, Zach Waldowski via swift-evolution 
>  wrote:
> 
> On Thu, Mar 16, 2017, at 02:23 PM, Matthew Johnson via swift-evolution wrote:
>> I don’t have an example but I don’t see a problem either.  There are two 
>> options for specifying the return type manually.  We can use the signature 
>> you used above and use `as` to specify the expected type:
>> 
>> let i = decode(.myKey) as Int
> 
> The awkwardness of this syntax is exactly what I'm referring to. Would a 
> beginner know to use "as Int" or ": Int"? Why would they? The "prettiness" of 
> the simple case doesn't make up for how difficult it is to understand and fix 
> its failure cases.
> 
> Any official Swift or Foundation API shouldn't, or shouldn't need to, make 
> use of "tricky" syntax.

Two arguments:

1) Most of the time, you will be setting the return value of decode into a 
typed property and will not need ‘as’.
2) Even when you do need it, its not tricky syntax: it’s the official way to 
direct the type inference engine in Swift.

David.

>> If we don’t support this in Foundation we will continue to see 3rd party 
>> libraries that do this.
> 
> The proposal's been out for less than 24 hours, is it really productive to 
> already be taking our ball and go home over such a minor thing?
> 
> Zach Waldowski
> z...@waldowski.me 
> 
> 
> 
> 
> ___
> 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] Foundation Swift Archival & Serialization

2017-03-16 Thread Itai Ferber via swift-evolution
I’m going to reply to this thread as a whole — apologies if 
there’s someone’s comment that I’ve missed.


This is something that has come up in internal review, and we’ve 
certainly given it thought. As Zach has already mentioned, the primary 
concern with overloading based on return type is ambiguity.
There are many cases in which Swift’s type system currently does not 
handle ambiguity in the way that you would expect, and it can be very 
surprising. For instance,


```swift
func foo() -> Int { return 42 }
func foo() -> Double { return .pi }
func consumesInt(_ x : Int) { print(x) }

let x = foo() // Ambiguous use of foo()
consumesInt(x) // Even though x is going to be used as an Int
let y: Int = x // Same here
```

`let x = foo() as Int` works now, but it actually didn’t always — 
until a somewhat recent version of Swift AFAICT, the only way to resolve 
the ambiguity was through `let x: Int = foo()`. This has since been 
fixed, but it was very confusing to try to figure out the unambiguous 
way to call it.


Keep in mind that this isn’t an unreasonable thing to want to do:

```swift
struct Foo {
var x: Int
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)

// Want to process an element before it’s assigned.
let x = container.decode(forKey: .x) // Ambiguous call

// Or whatever.
if x < 0 {
self.x = x + 100
else {
self.x = x * 200
}
}
}
```

You can write `let x: Int = container.decode(…)` or `let x = 
container.decode(…) as Int`, but this isn’t always intuitive.
Consider also that the metatype would also be necessary for 
`decode(_ type: Value.Type, forKey: Key) -> Value` 
because the return value of that certainly could be ambiguous in many 
cases.


Finally, the metatype arg allows you to express the following 
succinctly: `let v: SuperClass = container.decode(SubClass.self, forKey: 
.v)`.


In the general case (`decode`) we would need the 
metatype to avoid ambiguity. It’s not strictly necessary for primitive 
types, but helps in the case of ambiguity, and solves the conceptual 
overhead of "Why do I specify the type sometimes but not others? Why are 
some of these types special? Should I always provide the type? Why 
wouldn’t I?"


Matthew offered `func decode(_ key: Key, as type: T.Type = T.self) 
throws -> T` which looks appealing, but:


1. Doesn’t help resolve the ambiguity either
2. Allows for 3 ways of expressing the same thing (`let x: Int = 
decode(key)`, `let x = decode(key) as Int`, and `let x = decode(key, as: 
Int.self)`)


The cognitive overhead of figuring out all of the ambiguity goes away 
when we’re consistent everywhere.
FWIW, too, I am not convinced that Foundation should add API just 
because 3rd parties will add it. The ambiguity in the general case 
cannot be solved by wrappers, and I would prefer to provide one simple, 
consistent solution; if 3rd parties would like to add wrappers for their 
own sake, then I certainly encourage that.


On 16 Mar 2017, at 11:46, Matthew Johnson via swift-evolution wrote:

> On Mar 16, 2017, at 1:34 PM, Zach Waldowski via swift-evolution 
 wrote:


On Thu, Mar 16, 2017, at 02:23 PM, Matthew Johnson via 
swift-evolution wrote:
I don’t have an example but I don’t see a problem either.  There 
are two options for specifying the return type manually.  We can use 
the signature you used above and use `as` to specify the expected 
type:


let i = decode(.myKey) as Int


The awkwardness of this syntax is exactly what I'm referring to. 
Would a beginner know to use "as Int" or ": Int"? Why would they? The 
"prettiness" of the simple case doesn't make up for how difficult it 
is to understand and fix its failure cases.


Any official Swift or Foundation API shouldn't, or shouldn't need to, 
make use of "tricky" syntax.


I don’t think this is especially tricky.  Nevertheless, we can avoid 
requiring this syntax by moving the type argument to the end and 
providing a default.  But I think return type inference is worth 
supporting.  It has become widely adopted by the community already in 
this use case.




If we don’t support this in Foundation we will continue to see 3rd 
party libraries that do this.


The proposal's been out for less than 24 hours, is it really 
productive to already be taking our ball and go home over such a 
minor thing?


I don’t think that’s what I’m doing at all.  This is a fantastic 
proposal.  I’m still working through it and writing up my more 
detailed thoughts.


That said, as with many (most?) first drafts, there is room for 
improvement.  I think it’s worth pointing out the syntax that many 
of us would like to use for decoding and at least considering 
including it in the proposal.  If the answer is that it’s trivial 
for those who want to use subscripts to write the wrappers for return 
type inference and / or subscripts themselves that’s ok.  But 

Re: [swift-evolution] [Proposal] Foundation Swift Archival & Serialization

2017-03-16 Thread Itai Ferber via swift-evolution

Thanks for the thorough and detailed review, Brent! Responses inline.

On 15 Mar 2017, at 21:19, Brent Royal-Gordon wrote:

On Mar 15, 2017, at 3:40 PM, Itai Ferber via swift-evolution 
 wrote:


Hi everyone,

The following introduces a new Swift-focused archival and 
serialization API as part of the Foundation framework. We’re 
interested in improving the experience and safety of performing 
archival and serialization, and are happy to receive community 
feedback on this work.


Thanks to all of the people who've worked on this. It's a great 
proposal.



Specifically:

	• It aims to provide a solution for the archival of Swift struct 
and enum types


I see a lot of discussion here of structs and classes, and an example 
of an enum without associated values, but I don't see any discussion 
of enums with associated values. Can you sketch how you see people 
encoding such types?


For example, I assume that `Optional` is going to get some special 
treatment, but if it doesn't, how would you write its `encode(to:)` 
method?
`Optional` values are accepted and vended directly through the API. The 
`encode(_:forKey:)` methods take optional values directly, and 
`decodeIfPresent(_:forKey:)` vend optional values.


`Optional` is special in this way — it’s a primitive part of the 
system. It’s actually not possible to write an `encode(to:)` method 
for `Optional`, since the representation of null values is up to the 
encoder and the format it’s working in; `JSONEncoder`, for instance, 
decides on the representation of `nil` (JSON `null`). It wouldn’t be 
possible to ask `nil` to encode itself in a reasonable way.


What about a more complex enum, like the standard library's 
`UnicodeDecodingResult`:


enum UnicodeDecodingResult {
case emptyInput
case error
case scalarValue(UnicodeScalar)
}

Or, say, an `Error`-conforming type from one of my projects:

public enum SQLError: Error {
case connectionFailed(underlying: Error)
case executionFailed(underlying: Error, statement: SQLStatement)
case noRecordsFound(statement: SQLStatement)
case extraRecordsFound(statement: SQLStatement)
	case columnInvalid(underlying: Error, key: ColumnSpecifier, 
statement: SQLStatement)
	case valueInvalid(underlying: Error, key: AnySQLColumnKey, 
statement: SQLStatement)

}

(You can assume that all the types in the associated values are 
`Codable`.)
Sure — these cases specifically do not derive `Codable` conformance 
because the specific representation to choose is up to you. Two possible 
ways to write this, though there are many others (I’m simplifying 
these cases here a bit, but you can extrapolate this):


```swift
// Approach 1
// This produces either {"type": 0} for `.noValue`, or {"type": 1, 
"value": …} for `.associated`.

public enum EnumWithAssociatedValue : Codable {
case noValue
case associated(Int)

private enum CodingKeys : CodingKey {
case type
case value
}

public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let type = try container.decode(Int.self, forKey: .type)
switch type {
case 0:
self = .noValue
case 1:
let value = try container.decode(Int.self, forKey: .value)
self = .associated(value)
default:
throw …
}
}

public func encode(to encoder: Encoder) throws {
let container = encoder.container(keyedBy: codingKeys.self)
switch self {
case .noValue:
try container.encode(0, forKey: .type)
case .associated(let value):
try container.encode(1, forKey: .type)
try container.encode(value, forKey: .value)
}
}
}

// Approach 2
// Produces `0`, `1`, or `2` for `.noValue1`, `.noValue2`, and 
`.noValue3` respectively.
// Produces {"type": 3, "value": …} and {"type": 4, "value": …} for 
`.associated1` and `.associated2`.

public enum EnumWithAssociatedValue : Codable {
case noValue1
case noValue2
case noValue3
case associated1(Int)
case associated2(String)

private enum CodingKeys : CodingKey {
case type
case value
}

public init(from decoder: Decoder) throws {
if let container = try? decoder.singleValueContainer() {}
let type = container.decode(Int.self)
switch type {
case 0: self = .noValue1
case 1: self = .noValue2
case 2: self = .noValue3
default: throw …
}
} else {
let container = try decoder.container(keyedBy: 
CodingKeys.self)

let type = container.decode(Int.self, forKey: .type)
switch type {
case 3:
let value = container.decode(Int.self, forKey: .value)
self = 

Re: [swift-evolution] [Proposal] Foundation Swift Archival & Serialization

2017-03-16 Thread Matthew Johnson via swift-evolution

> On Mar 16, 2017, at 1:34 PM, Zach Waldowski via swift-evolution 
>  wrote:
> 
> On Thu, Mar 16, 2017, at 02:23 PM, Matthew Johnson via swift-evolution wrote:
>> I don’t have an example but I don’t see a problem either.  There are two 
>> options for specifying the return type manually.  We can use the signature 
>> you used above and use `as` to specify the expected type:
>> 
>> let i = decode(.myKey) as Int
> 
> The awkwardness of this syntax is exactly what I'm referring to. Would a 
> beginner know to use "as Int" or ": Int"? Why would they? The "prettiness" of 
> the simple case doesn't make up for how difficult it is to understand and fix 
> its failure cases.
> 
> Any official Swift or Foundation API shouldn't, or shouldn't need to, make 
> use of "tricky" syntax.

I don’t think this is especially tricky.  Nevertheless, we can avoid requiring 
this syntax by moving the type argument to the end and providing a default.  
But I think return type inference is worth supporting.  It has become widely 
adopted by the community already in this use case.

> 
>> If we don’t support this in Foundation we will continue to see 3rd party 
>> libraries that do this.
> 
> The proposal's been out for less than 24 hours, is it really productive to 
> already be taking our ball and go home over such a minor thing?

I don’t think that’s what I’m doing at all.  This is a fantastic proposal.  I’m 
still working through it and writing up my more detailed thoughts.

That said, as with many (most?) first drafts, there is room for improvement.  I 
think it’s worth pointing out the syntax that many of us would like to use for 
decoding and at least considering including it in the proposal.  If the answer 
is that it’s trivial for those who want to use subscripts to write the wrappers 
for return type inference and / or subscripts themselves that’s ok.  But it’s a 
fair topic for discussion and should at least be addressed as an alternative 
that was rejected for a specific reason.

> 
> Zach Waldowski
> z...@waldowski.me 
> 
> 
> 
> 
> ___
> 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] Foundation Swift Archival & Serialization

2017-03-16 Thread Zach Waldowski via swift-evolution
On Thu, Mar 16, 2017, at 02:23 PM, Matthew Johnson via swift-evolution wrote:
> I don’t have an example but I don’t see a problem either.  There are
> two options for specifying the return type manually.  We can use the
> signature you used above and use `as` to specify the expected type:
> 

> let i = decode(.myKey) as Int



The awkwardness of this syntax is exactly what I'm referring to. Would a
beginner know to use "as Int" or ": Int"? Why would they? The
"prettiness" of the simple case doesn't make up for how difficult it is
to understand and fix its failure cases.


Any official Swift or Foundation API shouldn't, or shouldn't need to,
make use of "tricky" syntax.


> If we don’t support this in Foundation we will continue to see 3rd
> party libraries that do this.


The proposal's been out for less than 24 hours, is it really productive
to already be taking our ball and go home over such a minor thing?


Zach Waldowski

z...@waldowski.me








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


Re: [swift-evolution] [Proposal] Foundation Swift Archival & Serialization

2017-03-16 Thread Matthew Johnson via swift-evolution

> On Mar 16, 2017, at 1:06 PM, David Hart via swift-evolution 
>  wrote:
> 
> 
> On 16 Mar 2017, at 16:53, Zach Waldowski  > wrote:
> 
>>> On Mar 16, 2017, at 3:09 AM, David Hart via swift-evolution 
>>> > wrote:
>>> 
>>> 2) Libraries like Marshal (https://github.com/utahiosmac/Marshal 
>>> ) and Unbox 
>>> (https://github.com/JohnSundell/Unbox 
>>> ) don’t require the decoding 
>>> functions to provide the type: those functions are generic on the return 
>>> turn and it’s automatically inferred:
>>> 
>>> func decode(key: Key) -> T
>>> 
>>> self.stringProperty = decode(key: .stringProperty) // correct 
>>> specialisation of the generic function chosen by the compiler
>>> 
>>> Is there a reason the proposal did not choose this solution? Its quite 
>>> sweet.
>> 
>> IMHO those are only “sweet” until you need to decode a value out to 
>> something other than a typed value, then it’s ambiguity city.
> 
> Other than a typed value? Can you give an example?

I don’t have an example but I don’t see a problem either.  There are two 
options for specifying the return type manually.  We can use the signature you 
used above and use `as` to specify the expected type:

let i = decode(.myKey) as Int

We can also use the type argument but provide a default value:

func decode(_ key: Key, as type: T.Type = T.self) throws -> T

let i = decode(key: .myKey, as: Int.self)

I think the Foundation team should strongly consider one of these signatures 
and allow us to rely on return type inference when desired.  If this isn’t 
provided by Foundation we’ll see a bunch of wrappers that do this.  Why not 
include it in the standard interface?  

The same argument can be made for providing a subscript instead of or in 
addition to `decode`.  Of course exposing a proper subscript interface isn’t 
possible until we have throwing subscripts.  Decoding is one of the major 
motivating use cases for throwing subscripts.  With Foundation tackling this 
topic in Swift 4 maybe it would be good to consider bringing throwing 
subscripts in scope and using them in the interface to KeyedDecodingContainer.  

Subscript with return type inference is the natural interface for a keyed 
decoder (obviously IMO).  If we don’t support this in Foundation we will 
continue to see 3rd party libraries that do this.  I think it would be better 
to provide the same interface and implementation to everyone directly in 
Foundation itself.

> 
>> There are many ways to solve that, but none of them are conducive to 
>> beginners. Using the metatype to seed the generic resolution is the only 
>> thing I’d get behind, personally.
>> 
>> Zach Waldowski
>> z...@waldowski.me 
>> 
> ___
> 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] Foundation Swift Archival & Serialization

2017-03-16 Thread David Hart via swift-evolution

> On 16 Mar 2017, at 16:53, Zach Waldowski  wrote:
> 
>> On Mar 16, 2017, at 3:09 AM, David Hart via swift-evolution 
>>  wrote:
>> 
>> 2) Libraries like Marshal (https://github.com/utahiosmac/Marshal) and Unbox 
>> (https://github.com/JohnSundell/Unbox) don’t require the decoding functions 
>> to provide the type: those functions are generic on the return turn and it’s 
>> automatically inferred:
>> 
>> func decode(key: Key) -> T
>> 
>> self.stringProperty = decode(key: .stringProperty) // correct specialisation 
>> of the generic function chosen by the compiler
>> 
>> Is there a reason the proposal did not choose this solution? Its quite sweet.
> 
> IMHO those are only “sweet” until you need to decode a value out to something 
> other than a typed value, then it’s ambiguity city.

Other than a typed value? Can you give an example?

> There are many ways to solve that, but none of them are conducive to 
> beginners. Using the metatype to seed the generic resolution is the only 
> thing I’d get behind, personally.
> 
> Zach Waldowski
> z...@waldowski.me
> 
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Foundation Swift Archival & Serialization

2017-03-16 Thread Joe Groff via swift-evolution

> On Mar 16, 2017, at 10:21 AM, Itai Ferber  wrote:
> 
> On 15 Mar 2017, at 19:12, Joe Groff wrote:
> 
> 
> On Mar 15, 2017, at 6:46 PM, Itai Ferber  wrote:
> 
> Thanks Joe, and thanks for passing this along!
> 
> To those who are curious, we use abstract base classes for a cascading list 
> of reasons:
> 
> • We need to be able to represent keyed encoding and decoding containers as 
> abstract types which are generic on a key type
> • There are two ways to support abstraction in this way: protocol & type 
> constraints, and generic types
> • Since Swift protocols are not generic, we unfortunately cannot write 
> protocol KeyedEncodingContainer { ... }, which is the 
> "ideal" version of what we're trying to represent
> • Let's try this with a protocol first (simplified here):
> 
> protocol Container {
> associatedtype Key : CodingKey
> }
> 
> func container(_ type: Key.Type) -> Cont 
> where Cont.Key == Key {
> // return something
> }
> 
> This looks promising so far — let's try to make it concrete:
> 
> struct ConcreteContainer : Container {
> typealias Key = K
> }
> 
> func container(_ type: Key.Type) -> Cont 
> where Cont.Key == Key {
> return ConcreteContainer() // error: Cannot convert return expression of 
> type 'ConcreteContainer' to return type 'Cont'
> }
> 
> Joe or anyone from the Swift team can describe this better, but this is my 
> poor-man's explanation of why this happens. Swift's type constraints are 
> "directional" in a sense. You can constrain a type going into a function, but 
> not out of a function. There is no type I could return from inside of 
> container() which would satisfy this constraint, because the constraint can 
> only be satisfied by turning Cont into a concrete type from the outside.
> 
> Okay, well let's try this:
> 
> func container... {
> return ConcreteContainer() as! Cont
> }
> 
> This compiles fine! Hmm, let's try to use it:
> 
> container(Int.self) // error: Generic parameter 'Cont' could not be inferred
> 
> The type constraint can only be fulfilled from the outside, not the inside. 
> The function call itself has no context for the concrete type that this would 
> return, so this is a no-go.
> 
> • If we can't do it with type constraints in this way, is it possible with 
> generic types? Yep! Generic types satisfy this without a problem. However, 
> since we don't have generic protocols, we have to use a generic abstract base 
> class to represent the same concept — an abstract container generic on the 
> type of key which dynamically dispatches to the "real" subclassed type
> 
> Hopes that gives some simplified insight into the nature of this decision.
> 
> I see. Protocols with associated types serve the same purpose as generic 
> interfaces in other languages, but we don't have the first-class support for 
> protocol types with associated type constraints (a value of type `Container 
> where Key == K`). That's something we'd like to eventually support. In other 
> places in the standard library, we wrtie the type-erased container by hand, 
> which is why we have `AnySequence`, `AnyCollection`, and `AnyHashable`. You 
> could probably do something similar here; that would be a bit awkward for 
> implementers, but might be easier to migrate forward to where we eventually 
> want to be with the language.
> 
> -Joe
> 
> Yep, that’s a good way to describe it.
> We could potentially do that as well, but adding another type like 
> AnyHashable or AnyCollection felt like a much more sweeping change, 
> considering that those require some special compiler magic themselves (and 
> we’d like to do as little of that as we can).

AnyCollection doesn't have any special compiler magic. AnyHashable's only magic 
is that it has implicit conversions, but that would become normal behavior once 
it can be replaced by a plain Hashable existential type.

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


Re: [swift-evolution] [Proposal] Foundation Swift Archival & Serialization

2017-03-16 Thread Itai Ferber via swift-evolution



On 15 Mar 2017, at 19:12, Joe Groff wrote:


On Mar 15, 2017, at 6:46 PM, Itai Ferber  wrote:

Thanks Joe, and thanks for passing this along!

To those who are curious, we use abstract base classes for a 
cascading list of reasons:


	• We need to be able to represent keyed encoding and decoding 
containers as abstract types which are generic on a key type
	• There are two ways to support abstraction in this way: protocol 
& type constraints, and generic types
		• Since Swift protocols are not generic, we unfortunately cannot 
write protocol KeyedEncodingContainer { ... }, which 
is the "ideal" version of what we're trying to represent

• Let's try this with a protocol first (simplified here):

protocol Container {
associatedtype Key : CodingKey
}

func container(_ type: Key.Type) 
-> Cont where Cont.Key == Key {

// return something
}

This looks promising so far — let's try to make it concrete:

struct ConcreteContainer : Container {
typealias Key = K
}

func container(_ type: Key.Type) 
-> Cont where Cont.Key == Key {
return ConcreteContainer() // error: Cannot convert return 
expression of type 'ConcreteContainer' to return type 'Cont'

}

Joe or anyone from the Swift team can describe this better, but this 
is my poor-man's explanation of why this happens. Swift's type 
constraints are "directional" in a sense. You can constrain a type 
going into a function, but not out of a function. There is no type I 
could return from inside of container() which would satisfy this 
constraint, because the constraint can only be satisfied by turning 
Cont into a concrete type from the outside.


Okay, well let's try this:

func container... {
return ConcreteContainer() as! Cont
}

This compiles fine! Hmm, let's try to use it:

container(Int.self) // error: Generic parameter 'Cont' could not be 
inferred


The type constraint can only be fulfilled from the outside, not the 
inside. The function call itself has no context for the concrete type 
that this would return, so this is a no-go.


	• If we can't do it with type constraints in this way, is it 
possible with generic types? Yep! Generic types satisfy this without 
a problem. However, since we don't have generic protocols, we have to 
use a generic abstract base class to represent the same concept — 
an abstract container generic on the type of key which dynamically 
dispatches to the "real" subclassed type


Hopes that gives some simplified insight into the nature of this 
decision.


I see. Protocols with associated types serve the same purpose as 
generic interfaces in other languages, but we don't have the 
first-class support for protocol types with associated type 
constraints (a value of type `Container where Key == K`). That's 
something we'd like to eventually support. In other places in the 
standard library, we wrtie the type-erased container by hand, which is 
why we have `AnySequence`, `AnyCollection`, and `AnyHashable`. You 
could probably do something similar here; that would be a bit awkward 
for implementers, but might be easier to migrate forward to where we 
eventually want to be with the language.


-Joe

Yep, that’s a good way to describe it.
We could potentially do that as well, but adding another type like 
`AnyHashable` or `AnyCollection` felt like a much more sweeping change, 
considering that those require some special compiler magic themselves 
(and we’d like to do as little of that as we can).
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] UInt64 indices broken

2017-03-16 Thread John McCall via swift-evolution

> On Mar 15, 2017, at 9:04 PM, G Alexander via swift-evolution 
>  wrote:
> 
> All,
> 
> Why does swift fails to fully implement UInt in any object, arrays, sequence, 
> range, etc
> 
> Initializer for Range, from "http://swiftdoc.org/v3.1/type/Range/;
> 
>  For example, passing a closed range with an upper bound of Int.max triggers 
> a runtime error, because the resulting half-open range would require an upper 
> bound of Int.max + 1, which is not representable as an Int.
> 
> So any algorithm that needs large arrays such that,   UInt64.max > index > 
> Int64  too bad?

You keep slipping between different types, so it's hard to figure out what 
you're asking about.

Ranges can be expressed using an arbitrary bound type, and Collections can be 
expressed using an arbitrary index type.  So if you want to have a collection 
whose index type is UInt64, you absolutely can.  The standard arrays use Int as 
their index type because (1) there's value in promoting a single integer type 
and (2) those types store their elements in memory, and the machine almost 
certainly cannot store anywhere near Int.max values in memory at once, even if 
they're a single byte apiece.

Closed ranges are implemented in terms of half-open ranges because trying to 
support both faithfully would massively complicate the programming model around 
ranges.  Losing a single element of capacity from integer-indexed collections 
is comparatively innocuous.

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


Re: [swift-evolution] UInt64 indices broken

2017-03-16 Thread Xiaodi Wu via swift-evolution
This is a deliberate design choice. As written in The Swift Programming
Language:

"Use UInt only when you specifically need an unsigned integer type with the
same size as the platform’s native word size. If this is not the case, Int
is preferred, even when the values to be stored are known to be
non-negative. A consistent use of Int for integer values aids code
interoperability, avoids the need to convert between different number
types, and matches integer type inference, as described in Type Safety and
Type Inference."

You are correct that arrays with count greater than Int.max are unsupported.
On Thu, Mar 16, 2017 at 11:13 G Alexander via swift-evolution <
swift-evolution@swift.org> wrote:

> All,
>
> Why does swift fails to fully implement UInt in any object, arrays,
> sequence, range, etc
>
> Initializer for Range, from "http://swiftdoc.org/v3.1/type/Range/;
>
>  For example, passing a closed range with an upper bound of Int.max
> triggers a runtime error, because the resulting half-open range would
> require an upper bound of Int.max + 1, which is not representable as an Int.
>
> So any algorithm that needs large arrays such that,   UInt64.max > index >
> Int64  too bad?
>
> ___
> 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] UInt64 indices broken

2017-03-16 Thread G Alexander via swift-evolution
All,

Why does swift fails to fully implement UInt in any object, arrays, sequence, 
range, etc

Initializer for Range, from "http://swiftdoc.org/v3.1/type/Range/;

 For example, passing a closed range with an upper bound of Int.max triggers a 
runtime error, because the resulting half-open range would require an upper 
bound of Int.max + 1, which is not representable as an Int.

So any algorithm that needs large arrays such that,   UInt64.max > index > 
Int64  too bad?

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


Re: [swift-evolution] [Proposal] Foundation Swift Archival & Serialization

2017-03-16 Thread Zach Waldowski via swift-evolution
> On Mar 16, 2017, at 3:09 AM, David Hart via swift-evolution 
>  wrote:
> 
> 2) Libraries like Marshal (https://github.com/utahiosmac/Marshal 
> ) and Unbox 
> (https://github.com/JohnSundell/Unbox ) 
> don’t require the decoding functions to provide the type: those functions are 
> generic on the return turn and it’s automatically inferred:
> 
> func decode(key: Key) -> T
> 
> self.stringProperty = decode(key: .stringProperty) // correct specialisation 
> of the generic function chosen by the compiler
> 
> Is there a reason the proposal did not choose this solution? Its quite sweet.

IMHO those are only “sweet” until you need to decode a value out to something 
other than a typed value, then it’s ambiguity city. There are many ways to 
solve that, but none of them are conducive to beginners. Using the metatype to 
seed the generic resolution is the only thing I’d get behind, personally.

Zach Waldowski
z...@waldowski.me

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


Re: [swift-evolution] [Proposal] Foundation Swift Encoders

2017-03-16 Thread Ben Rimmington via swift-evolution


Could the `JSONEncoder.OutputFormatting.prettyPrinted` case include the 
**stable ordering** of keys?

-- Ben

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


[swift-evolution] [Draft] extend API for managing tail-allocated buffers

2017-03-16 Thread Alexey Komnin via swift-evolution
Hi there,

I've written up a proposal

and would love to hear your feedback on it!

Best Regards,
Alex Komnin

P.S. Based on discussion in https://lists.swift.org/pip
ermail/swift-evolution/Week-of-Mon-20161212/029415.html

Extend API for managing tail allocated buffers

   - Proposal: SE-
   

   - Authors: Alexey Komnin 
   - Review Manager: TBD
   - Status: Awaiting review


Introduction

Some Swift intrinsics (allocWithTailElems_{n}) are widely used by Swift
standard library to implement tail-allocated buffers. As intrinsics are
used only within standard library, they are not available for ordinary
developers. Hence, there is no way to effectively implement custom
containers like OrderedSet or LRU-cache.

On the other hand, there is a suitable approach to create and manage
single-area tail-allocated buffer. Swift provides a class named
ManagedBuffer. Actually, class method
ManagedBuffer.create(minimumCapacity:makingHeaderWith:) is just a wrapper
over allocWithTailElems_1 builtin. You may use that class as a storage for
elements of contiguous collection: Array or RingBuffer. Unfortunately,
Swift doesn't provde wrappers for allocWithTailElems_2,
allocWithTailElems_3 etc.
builtins.

This proposal outlines a new API for managing multi-area tail-allocated
buffers. It is supposed to extend current implementation of ManagedBuffer to
support 2- and 3-areas tail-allocated buffers.

Swift-evolution thread: TBD


Motivation

Collections in Swift are implemnted using tail-allocated buffers. A handful
of intrinsics are available for developers of swift standard library to
allocate and manage data stored in them. For example, the buffer used by
Array is implemented with allocWithTailElems_1 routine, which is able to
allocate contiguous buffer for N elements of type U. Set is implemented
with allocWithTailElems_3 routine, which is able to allocate
contiguous buffer consisted of three areas for elements of types T, U and V.

Application developers can't use these instrinsics. One is supposed to use
ManagedBuffer instead, which is a simple wrapper over the single-area
tail-allocated buffer. It uses allocWithTailElems_1 to allocate storage
for elements of type U the same way the Array container does. So it may be
used to implement containers with contiguous storage: Array or Queue.

Yet there is no API to create or manage multi-area tail-allocated buffers
in stdlib. Routines allocWithTailElems_{n} are neither wrapped by
ManagedBuffer_{n} classes nor exposed to be used by developers. Instead,
developers are forced to use ManagedBuffer and do lots of pointer
arithmetic.
Proposed
solution

This proposal introduces a new class ManagedBufferTuple and a list of
traits for single and multiple areas cases. The traits are to keep all
internal information about structure of the areas.

These changes make it simple to implement multi-area buffers as simple as
single-area. Example:

class TwoAreasManagedBuffer: ManagedBufferTuple> {
static func create(minimumCapacity: Int) -> TwoAreasManagedBuffer {
let p = create(minimumCapacity1: minimumCapacity,
minimumCapacity2: minimumCapacity) { buffer in
return CustomHeader(capacity1: buffer.capacity1,
capacity2: buffer.capacity2)
}
return unsafeDowncast(p, to: self)
}
}

Detailed
Design

ManagedBufferTuple

The standard library introduces new class ManagedBufferTuple. The base
interface of the class is simple and minimalistic:

open class ManagedBufferTuple {
  /// Call `body` with an `UnsafeMutablePointer` to the stored  ///
`Header`.  ///  /// - Note: This pointer is valid only for the
duration of the  ///   call to `body`.  public final func
withUnsafeMutablePointerToHeader(
_ body: (UnsafeMutablePointer) throws -> R) rethrows -> R

  /// The stored `Header` instance.  ///  /// During instance
creation, in particular during  ///
`ManagedBufferTupleFactory.create`'s call to initialize,   ///
`ManagedBufferTuple`'s `header` property is as-yet uninitialized,
/// and therefore reading the `header` property during

Re: [swift-evolution] [Proposal] Foundation Swift Archival & Serialization

2017-03-16 Thread Vincent Esche via swift-evolution
On Thu, Mar 16, 2017 at 1:45 AM, Zach Waldowski via swift-evolution <
swift-evolution@swift.org> wrote:

> Holy cow. There's much to digest here (so much so that my initial
> response, which quoted its content, was denied by the mailing list). After
> an initial reading, I don't just want this now, I want it yesterday. I'm
> already imaging the encoder/decoders I want to build. Very exciting.
>

+1 on this (having skimmed through it briefly)!
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Foundation Swift Encoders

2017-03-16 Thread Brent Royal-Gordon via swift-evolution
> On Mar 15, 2017, at 3:43 PM, Itai Ferber via swift-evolution 
>  wrote:
> 
> Hi everyone,
> This is a companion proposal to the Foundation Swift Archival & Serialization 
> API. This introduces new encoders and decoders to be used as part of this 
> system.
> The proposal is available online and inlined below.

Executive summary: I like where you're going with this, but I'm worried about 
flexibility.

I'm not going to quote every bit of the JSON section because Apple Mail seems 
to destroy the formatting when I reply, but: I think you've identified several 
of the most important customization points (Date, Data, and illegal Floats). 
However, I think:

* People may want to map illegal Floats to legal floating-point values (say, 
`greatestFiniteMagnitude`, `-greatestFiniteMagnitude`, and `0`) or map them to 
`null`s. They may also want different behavior for different things: imagine 
`(positiveInfinity: Double.greatestFiniteMagnitude, negativeInfinity: 
-Double.greatestFiniteMagnitude, nan: .throw)`.

* Large integers are another big concern that you don't address. Because JSON 
only supports doubles, APIs that use 64-bit IDs often need them to be passed as 
strings, frequently with a different key ("id_str" instead of "id").

* For that matter, style and capitalization are a problem. JSON style varies, 
but it *tends* to be snake_case, where Cocoa favors camelCase. You can address 
this at the CodingKey level by manually specifying string equivalents of all 
the coding keys, but that's kind of a pain, and it affects all of your code and 
all of your serializations.

I'm sorely tempted to suggest that we give the JSON encoder and decoder a 
delegate:

public protocol JSONCodingDelegate {
/// Returns the string name to be used when encoding or 
decoding the given CodingKey as JSON.
/// 
/// - Returns: The string to use, or `nil` for the default.
func jsonName(for key: CodingKey, at keyPath: [CodingKey], in 
encoderOrDecoder: AnyObject) throws -> String?

// These are used when encoding/decoding any of the integer 
types.
func jsonValue(from integer: Int64, at keyPath: [CodingKey], in 
encoder: JSONEncoder) throws -> JSONValue?
func integer(from jsonValue: JSONValue, at keyPath: 
[CodingKey], in decoder: JSONDecoder) throws -> Int64?

// These are used when encoding/decoding any of the 
floating-point types.
func jsonValue(from number: Double, at keyPath: [CodingKey], in 
encoder: JSONEncoder) throws -> JSONValue?
func number(from jsonValue: JSONValue, at keyPath: [CodingKey], 
in decoder: JSONDecoder) throws -> Double?

// These are used when encoding/decoding Date.
func jsonValue(from date: Date, at keyPath: [CodingKey], in 
encoder: JSONEncoder) throws -> JSONValue?
func date(from jsonValue: JSONValue, at keyPath: [CodingKey], 
in decoder: JSONDecoder) throws -> Date?

// These are used when encoding/decoding Data.
func jsonValue(from data: Data, at keyPath: [CodingKey], in 
encoder: JSONEncoder) throws -> JSONValue?
func data(from jsonValue: JSONValue, at keyPath: [CodingKey], 
in decoder: JSONDecoder) throws -> Data?

func jsonValue(from double: Double, at keyPath: [CodingKey], in 
encoder: JSONEncoder) throws -> JSONValue?
func integer(from jsonValue: JSONValue, at keyPath: 
[CodingKey], in decoder: JSONDecoder) throws -> Double?
}
public enum JSONValue {
case string(String)
case number(Double)
case bool(Bool)
case object([String: JSONValue])
case array([JSONValue])
case null
}

Or, perhaps, that a more general form of this delegate be available on all 
encoders and decoders. But that may be overkill, and even if it *is* a good 
idea, it's one we can add later.

> Property List
> 
> We also intend to support the property list format, with PropertyListEncoder 
> and PropertyListDecoder:

No complaints here.

> Foundation-Provided Errors
> 
> Along with providing the above encoders and decoders, we would like to 
> promote the use of a common set of error codes and messages across all new 
> encoders and decoders. A common vocabulary of expected errors allows 
> end-users to write code agnostic about the specific encoder/decoder 
> implementation they are working with, whether first-party or third-party:
> 
> extension CocoaError.Code {
> /// Thrown when a value incompatible with the output format is encoded.
> public static var coderInvalidValue: CocoaError.Code
> 
> /// Thrown when a value of a given type is requested but the encountered 
> value is of an incompatible type.
> public 

Re: [swift-evolution] [Proposal] Foundation Swift Archival & Serialization

2017-03-16 Thread David Hart via swift-evolution
First of all, great proposal :D

Brent, earlier in the thread makes a lot of good points. But I’d still like to 
discuss two subjects:

1) What makes the proposal really stand on its feet compared to third-party 
libraries is the compiler generation magic. I feel divided about it. On one 
hand, this is the only solution today to have this level of type and key 
safety. But on another hand, I have the impression that future versions of 
Swift (with more reflection, property behaviours, lenses, etc…) would 
dramatically affect how this subject is treated and implemented. Are you 
worried that we are asking the compiler to do work which might be un-necessary 
in the future? That this topic would be better expressed with more powerful 
language features? Any plans to migrate for this API to smoothly migrate to 
those features in the future?

2) Libraries like Marshal (https://github.com/utahiosmac/Marshal 
) and Unbox 
(https://github.com/JohnSundell/Unbox ) 
don’t require the decoding functions to provide the type: those functions are 
generic on the return turn and it’s automatically inferred:

func decode(key: Key) -> T

self.stringProperty = decode(key: .stringProperty) // correct specialisation of 
the generic function chosen by the compiler

Is there a reason the proposal did not choose this solution? Its quite sweet.

> Swift Archival & Serialization
> Proposal: SE- 
> Author(s): Itai Ferber , Michael LeHew 
> , Tony Parker 
> Review Manager: TBD
> Status: Awaiting review
> Associated PRs:
> #8124 
> #8125 ___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Foundation Swift Archival & Serialization

2017-03-16 Thread Goffredo Marocchi via swift-evolution


Sent from my iPhone

> On 16 Mar 2017, at 01:18, Joe Groff via swift-evolution 
>  wrote:
> 
> Congrats on getting this out! A question from the field:
> 
> https://twitter.com/mdiep/status/842178457115230210 Why does the Swift 
> Serialization API proposal use abstract base classes?
> 

Hopefully because we realise we need abstract classes as a feature ;)? 

> -Joe
> 
> 
>> On Mar 15, 2017, at 3:40 PM, Itai Ferber via swift-evolution 
>>  wrote:
>> 
>> Hi everyone,
>> 
>> The following introduces a new Swift-focused archival and serialization API 
>> as part of the Foundation framework. We’re interested in improving the 
>> experience and safety of performing archival and serialization, and are 
>> happy to receive community feedback on this work.
>> Because of the length of this proposal, the Appendix and Alternatives 
>> Considered sections have been omitted here, but are available in the full 
>> proposal on the swift-evolution repo. The full proposal also includes an 
>> Unabridged API for further consideration.
>> 
>> Without further ado, inlined below.
>> 
>> — Itai
>> 
>> Swift Archival & Serialization
>>• Proposal: SE-
>>• Author(s): Itai Ferber, Michael LeHew, Tony Parker
>>• Review Manager: TBD
>>• Status: Awaiting review
>>• Associated PRs:
>>• #8124
>>• #8125
>> Introduction
>> Foundation's current archival and serialization APIs (NSCoding, 
>> NSJSONSerialization, NSPropertyListSerialization, etc.), while fitting for 
>> the dynamism of Objective-C, do not always map optimally into Swift. This 
>> document lays out the design of an updated API that improves the developer 
>> experience of performing archival and serialization in Swift.
>> 
>> Specifically:
>> 
>>• It aims to provide a solution for the archival of Swift struct and enum 
>> types
>>• It aims to provide a more type-safe solution for serializing to 
>> external formats, such as JSON and plist
>> Motivation
>> The primary motivation for this proposal is the inclusion of native Swift 
>> enum and struct types in archival and serialization. Currently, developers 
>> targeting Swift cannot participate in NSCoding without being willing to 
>> abandon enum and structtypes — NSCoding is an @objc protocol, conformance to 
>> which excludes non-class types. This is can be limiting in Swift because 
>> small enums and structs can be an idiomatic approach to model 
>> representation; developers who wish to perform archival have to either forgo 
>> the Swift niceties that constructs like enumsprovide, or provide an 
>> additional compatibility layer between their "real" types and their 
>> archivable types.
>> 
>> Secondarily, we would like to refine Foundation's existing serialization 
>> APIs (NSJSONSerialization and NSPropertyListSerialization) to better match 
>> Swift's strong type safety. From experience, we find that the conversion 
>> from the unstructured, untyped data of these formats into strongly-typed 
>> data structures is a good fit for archival mechanisms, rather than taking 
>> the less safe approach that 3rd-party JSON conversion approaches have taken 
>> (described further in an appendix below).
>> 
>> We would like to offer a solution to these problems without sacrificing ease 
>> of use or type safety.
>> 
>> Agenda
>> This proposal is the first stage of three that introduce different facets of 
>> a whole Swift archival and serialization API:
>> 
>>• This proposal describes the basis for this API, focusing on the 
>> protocols that users adopt and interface with
>>• The next stage will propose specific API for new encoders
>>• The final stage will discuss how this new API will interop with 
>> NSCoding as it is today
>> SE- provides stages 2 and 3.
>> 
>> Proposed solution
>> We will be introducing the following new types:
>> 
>>• protocol Codable: Adopted by types to opt into archival. Conformance 
>> may be automatically derived in cases where all properties are also Codable.
>>• protocol CodingKey: Adopted by types used as keys for keyed containers, 
>> replacing String keys with semantic types. Conformance may be automatically 
>> derived in most cases.
>>• protocol Encoder: Adopted by types which can take Codable values and 
>> encode them into a native format.
>>• class KeyedEncodingContainer: Subclasses of this 
>> type provide a concrete way to store encoded values by CodingKey. Types 
>> adopting Encoder should provide subclasses of KeyedEncodingContainer to vend.
>>• protocol SingleValueEncodingContainer: Adopted by types which 
>> provide a concrete way to store a single encoded value. Types adopting 
>> Encoder should provide types conforming to SingleValueEncodingContainer to 
>> vend (but in many cases will be able to conform to it themselves).
>>• protocol Decoder: Adopted by types which can take payloads in a native 
>> format and decode Codable values 

Re: [swift-evolution] [Proposal] Foundation Swift Archival & Serialization

2017-03-16 Thread Brent Royal-Gordon via swift-evolution
> On Mar 15, 2017, at 9:19 PM, Brent Royal-Gordon  
> wrote:
> 
> I think we'd be better off having `encode(_:forKey:)` not take an optional; 
> instead, we should have `Optional` conform to `Codable` and behave in some 
> appropriate way. Exactly how to implement it might be a little tricky because 
> of nested optionals; I suppose a `none` would have to measure how many levels 
> of optionality there are between it and a concrete value, and then encode 
> that information into the data. I think our `NSNull` bridging is doing 
> something broadly similar right now.
> 
> I know that this is not the design you would use in Objective-C, but Swift 
> uses `Optional` differently from how Objective-C uses `nil`. Swift APIs 
> consider `nil` and absent to be different things; where they can both occur, 
> good Swift APIs use doubled-up Optionals to be precise about the situation. I 
> think the design needs to be a little different to accommodate that.

Re-reading this after sending it, I realized I should probably be a lot more 
concrete about what I envision here.

Basically, what I think is:

* There should be primitives for `encode(_ value: NSNull)` and `decode(_ type: 
NSNull.Type)`. Yes, even though it's a singleton. In JSON, this should 
emit/read a `null`; in plist format, I suppose it will simply have to interpret 
absence of the corresponding key as `null`, because there's nothing better we 
can do there.

* An `Optional.some(x)` should encode as an `x` would.

* An `Optional.none`, where `Wrapped` is not itself an `Optional`, should 
encode as an `NSNull`.

* An `Optional.none`, where `Wrapped` *is* itself an `Optional`, should encode 
as one of the Swift runtime's magic optional sentinel objects.

That will do the best job we can manage of correctly representing nested 
optionals.

-- 
Brent Royal-Gordon
Architechies

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