Re: [swift-evolution] [draft] Target environment platform condition

2017-10-24 Thread David Sweeris via swift-evolution
One quick question... WRT `os()`, should that take a string instead of some 
keywordish thing? There's at least one OS which has a Swift port, but doesn't 
show up on that list (Haiku: 
https://www.haiku-os.org/blog/return0e/2017-08-28_gsoc_2017_porting_swift_to_haiku_-_final_report/
 
)

- Dave Sweeris

> On Oct 24, 2017, at 8:05 PM, Graydon Hoare via swift-evolution 
>  wrote:
> 
> Hi,
> 
> I'd like to propose a variant of a very minor, additive proposal Erica Sadun 
> posted last year, that cleans up a slightly messy idiomatic use of 
> conditional compilation in libraries. The effects should be quite limited; 
> I'd call it a "standard library" addition except that the repertoire of 
> compiler-control statements isn't strictly part of the stdlib.
> 
> Proposal is here: 
> https://gist.github.com/graydon/809af2c726cb1a27af64435e47ef4e5d 
> 
> 
> Implementation (minus fixits) is here: 
> https://github.com/graydon/swift/commit/16493703ea297a1992ccd0fc4d2bcac7d078c982
>  
> 
> 
> Feedback appreciated,
> 
> -Graydon
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

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


Re: [swift-evolution] [draft] Target environment platform condition

2017-10-24 Thread Xiaodi Wu via swift-evolution
Seems useful and well thought-out. The name is justifiable and sufficiently
clear.


On Tue, Oct 24, 2017 at 10:05 PM, Graydon Hoare via swift-evolution <
swift-evolution@swift.org> wrote:

> Hi,
>
> I'd like to propose a variant of a very minor, additive proposal Erica
> Sadun posted last year, that cleans up a slightly messy idiomatic use of
> conditional compilation in libraries. The effects should be quite limited;
> I'd call it a "standard library" addition except that the repertoire of
> compiler-control statements isn't strictly part of the stdlib.
>
> Proposal is here: https://gist.github.com/graydon/
> 809af2c726cb1a27af64435e47ef4e5d
>
> Implementation (minus fixits) is here: https://github.com/
> graydon/swift/commit/16493703ea297a1992ccd0fc4d2bcac7d078c982
>
> Feedback appreciated,
>
> -Graydon
>
>
> ___
> 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] [draft] Target environment platform condition

2017-10-24 Thread Graydon Hoare via swift-evolution
Hi,

I'd like to propose a variant of a very minor, additive proposal Erica Sadun 
posted last year, that cleans up a slightly messy idiomatic use of conditional 
compilation in libraries. The effects should be quite limited; I'd call it a 
"standard library" addition except that the repertoire of compiler-control 
statements isn't strictly part of the stdlib.

Proposal is here: 
https://gist.github.com/graydon/809af2c726cb1a27af64435e47ef4e5d 


Implementation (minus fixits) is here: 
https://github.com/graydon/swift/commit/16493703ea297a1992ccd0fc4d2bcac7d078c982
 


Feedback appreciated,

-Graydon

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


Re: [swift-evolution] Pitch: Deprecate/remove AnyObject method dispatch

2017-10-24 Thread Slava Pestov via swift-evolution
You can implement an @objc protocol with an optional requirement, and make 
NSObject conform to it.

Slava

> On Oct 24, 2017, at 4:05 PM, Charles Srstka  wrote:
> 
>> On Oct 24, 2017, at 5:02 PM, Slava Pestov via swift-evolution 
>> > wrote:
>> 
>> Thoughts? Does anyone actually rely on this feature, instead of just 
>> stumbling on it by accident once in a while?
> 
> The main thing I can think of off the top of my head is getting the tag from 
> the sender in an IBAction:
> 
> @IBAction private func someAction(_ sender: Any?) {
> guard let tag = (sender as AnyObject?)?.tag as Int? else { return }
> 
> ...
> }
> 
> Unfortunately given how many unrelated Cocoa objects there are that implement 
> -tag, it’s not really practical to implement this without the AnyObject 
> dispatch. If a TagContaining protocol could be introduced and all the objects 
> that implement -tag could be made to conform to it, then that would work 
> around the problem (I believe I pitched this at some point long ago, but 
> without catching any interest).
> 
> Charles
> 

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


Re: [swift-evolution] Pitch: Deprecate/remove AnyObject method dispatch

2017-10-24 Thread Charles Srstka via swift-evolution
> On Oct 24, 2017, at 5:02 PM, Slava Pestov via swift-evolution 
>  wrote:
> 
> Thoughts? Does anyone actually rely on this feature, instead of just 
> stumbling on it by accident once in a while?

The main thing I can think of off the top of my head is getting the tag from 
the sender in an IBAction:

@IBAction private func someAction(_ sender: Any?) {
guard let tag = (sender as AnyObject?)?.tag as Int? else { return }

...
}

Unfortunately given how many unrelated Cocoa objects there are that implement 
-tag, it’s not really practical to implement this without the AnyObject 
dispatch. If a TagContaining protocol could be introduced and all the objects 
that implement -tag could be made to conform to it, then that would work around 
the problem (I believe I pitched this at some point long ago, but without 
catching any interest).

Charles

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


Re: [swift-evolution] Pitch: Member lookup on String should not find members of NSString

2017-10-24 Thread Slava Pestov via swift-evolution
I think to maintain source compatibility, the old behavior would be preserved 
until/if we remove -swift-version 4 mode. By deprecating it though, we won’t 
have to devote as much time to maintaining it going forward.

Slava

> On Oct 24, 2017, at 3:54 PM, Philippe Hausler  wrote:
> 
> I think any serious proposal with the removal of APIs would need to consider 
> source compatibility and to do so you should likely audit the API surface 
> area that is being offered (and replace it via the NSStringAPI.swift 
> extension)
> 
>> On Oct 24, 2017, at 3:12 PM, Slava Pestov via swift-evolution 
>>  wrote:
>> 
>> Perhaps you could write up a proposal to outline the missing functionality 
>> :-)
>> 
>> Slava
>> 
>>> On Oct 24, 2017, at 3:09 PM, Jonathan Hull  wrote:
>>> 
>>> I would feel better about it if String gained a lot of the utility of 
>>> NSString (so that we don’t have to go to NSString all the time for methods)
>>> 
>>> Thanks,
>>> Jon
>>> 
 On Oct 24, 2017, at 3:00 PM, Slava Pestov via swift-evolution 
  wrote:
 
 Hi,
 
 Members of NSString, except those defined in Foundation, are available on 
 values of type String. For example,
 
 extension NSString {
 @objc func foo() {}
 }
 
 let s: String = “hello”
 
 s.foo()
 
 We don’t do this for any other bridged types, for instance NSArray methods 
 are not imported as Array methods. It’s literally a special case in the 
 type checker for member lookup on String.
 
 This behavior doesn’t really much sense conceptually and it was put in as 
 a stop-gap in Swift 1 to beef up the String API. I would like to phase it 
 out as follows:
 
 - Unconditional warning in Swift 4.1, with a fixit to insert an ‘as 
 NSString’ cast
 - Error in Swift 5 with -swift-version 5
 
 What does everyone think about this?
 
 Slava
 ___
 swift-evolution mailing list
 swift-evolution@swift.org
 https://lists.swift.org/mailman/listinfo/swift-evolution
>>> 
>> 
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 

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


Re: [swift-evolution] Pitch: Member lookup on String should not find members of NSString

2017-10-24 Thread Philippe Hausler via swift-evolution
I think any serious proposal with the removal of APIs would need to consider 
source compatibility and to do so you should likely audit the API surface area 
that is being offered (and replace it via the NSStringAPI.swift extension)

> On Oct 24, 2017, at 3:12 PM, Slava Pestov via swift-evolution 
>  wrote:
> 
> Perhaps you could write up a proposal to outline the missing functionality :-)
> 
> Slava
> 
>> On Oct 24, 2017, at 3:09 PM, Jonathan Hull  wrote:
>> 
>> I would feel better about it if String gained a lot of the utility of 
>> NSString (so that we don’t have to go to NSString all the time for methods)
>> 
>> Thanks,
>> Jon
>> 
>>> On Oct 24, 2017, at 3:00 PM, Slava Pestov via swift-evolution 
>>>  wrote:
>>> 
>>> Hi,
>>> 
>>> Members of NSString, except those defined in Foundation, are available on 
>>> values of type String. For example,
>>> 
>>> extension NSString {
>>> @objc func foo() {}
>>> }
>>> 
>>> let s: String = “hello”
>>> 
>>> s.foo()
>>> 
>>> We don’t do this for any other bridged types, for instance NSArray methods 
>>> are not imported as Array methods. It’s literally a special case in the 
>>> type checker for member lookup on String.
>>> 
>>> This behavior doesn’t really much sense conceptually and it was put in as a 
>>> stop-gap in Swift 1 to beef up the String API. I would like to phase it out 
>>> as follows:
>>> 
>>> - Unconditional warning in Swift 4.1, with a fixit to insert an ‘as 
>>> NSString’ cast
>>> - Error in Swift 5 with -swift-version 5
>>> 
>>> What does everyone think about this?
>>> 
>>> Slava
>>> ___
>>> swift-evolution mailing list
>>> swift-evolution@swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> 
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

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


Re: [swift-evolution] Pitch: Deprecate/remove AnyObject method dispatch

2017-10-24 Thread Slava Pestov via swift-evolution
It is possible that they implement equality, but not hashing. So two equal 
values could hash differently. I don’t really know how NSObject implements but 
stuff, sorry.

Slava

> On Oct 24, 2017, at 3:26 PM, Jon Shier  wrote:
> 
>   Thanks, Slava, that works. Do you have any idea why that works, but 
> sets of the two arrays are always disjoint? The Set method works for 
> SecCertificate but not SecKey.
> 
> 
> 
> Jon
> 
> 
>> On Oct 24, 2017, at 6:10 PM, Slava Pestov  wrote:
>> 
>> isEqual is defined on NSObject. You could also try using an array of 
>> AnyHashable and calling == instead of isEqual.
>> 
>> Slava
>> 
>>> On Oct 24, 2017, at 3:09 PM, Jon Shier  wrote:
>>> 
>>> Slava:
>>> How would this change affect this code from Alamofire, used to compare 
>>> two SecKey instances for public key pinning:
>>> 
>>> outerLoop: for serverPublicKey in ServerTrustPolicy.publicKeys(for: 
>>> serverTrust) as [AnyObject] {
>>>  for pinnedPublicKey in pinnedPublicKeys as [AnyObject] {
>>>  if serverPublicKey.isEqual(pinnedPublicKey) {
>>>  serverTrustIsValid = true
>>>  break outerLoop
>>>  }
>>>  }
>>> }
>>> 
>>> I’m not sure why, but the AnyObject casting makes this work correctly, even 
>>> in Swift 4. I’ve tried to “modernize” it by using Sets (compare the pinned 
>>> keys with the available keys Sets) but it doesn’t work (hash implementation 
>>> for SecKey is weird?).  I’m guessing that with the AnyObject case and 
>>> isEqual, some underlying implementation is changed and equality works 
>>> properly (or well enough for this use). I’m happy to get rid of this hack, 
>>> but I’m not sure of any other method to accomplish our goals here.
>>> 
>>> 
>>> 
>>> Jon Shier
>>> 
 On Oct 24, 2017, at 6:02 PM, Slava Pestov via swift-evolution 
  wrote:
 
 Hi all,
 
 Dynamic dispatch of methods through AnyObject is a source of 
 implementation complexity, has many known bugs which we are not going to 
 fix, and no longer makes sense now in an id-as-Any world; AnyObject is not 
 the ‘common currency’ type for arbitrary Objective-C objects anymore.
 
 I would like to propose we deprecate it as follows:
 
 - Unconditional warning in Swift 4.1, with a fixit to add an ‘as’ cast to 
 cast the base value to the right type
 - Error in Swift 5 in -swift-version 5 mode
 
 Thoughts? Does anyone actually rely on this feature, instead of just 
 stumbling on it by accident once in a while?
 
 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] Pitch: Deprecate/remove AnyObject method dispatch

2017-10-24 Thread Jon Shier via swift-evolution
Thanks, Slava, that works. Do you have any idea why that works, but 
sets of the two arrays are always disjoint? The Set method works for 
SecCertificate but not SecKey.



Jon


> On Oct 24, 2017, at 6:10 PM, Slava Pestov  wrote:
> 
> isEqual is defined on NSObject. You could also try using an array of 
> AnyHashable and calling == instead of isEqual.
> 
> Slava
> 
>> On Oct 24, 2017, at 3:09 PM, Jon Shier  wrote:
>> 
>> Slava:
>>  How would this change affect this code from Alamofire, used to compare 
>> two SecKey instances for public key pinning:
>> 
>> outerLoop: for serverPublicKey in ServerTrustPolicy.publicKeys(for: 
>> serverTrust) as [AnyObject] {
>>   for pinnedPublicKey in pinnedPublicKeys as [AnyObject] {
>>   if serverPublicKey.isEqual(pinnedPublicKey) {
>>   serverTrustIsValid = true
>>   break outerLoop
>>   }
>>   }
>> }
>> 
>> I’m not sure why, but the AnyObject casting makes this work correctly, even 
>> in Swift 4. I’ve tried to “modernize” it by using Sets (compare the pinned 
>> keys with the available keys Sets) but it doesn’t work (hash implementation 
>> for SecKey is weird?).  I’m guessing that with the AnyObject case and 
>> isEqual, some underlying implementation is changed and equality works 
>> properly (or well enough for this use). I’m happy to get rid of this hack, 
>> but I’m not sure of any other method to accomplish our goals here.
>> 
>> 
>> 
>> Jon Shier
>> 
>>> On Oct 24, 2017, at 6:02 PM, Slava Pestov via swift-evolution 
>>>  wrote:
>>> 
>>> Hi all,
>>> 
>>> Dynamic dispatch of methods through AnyObject is a source of implementation 
>>> complexity, has many known bugs which we are not going to fix, and no 
>>> longer makes sense now in an id-as-Any world; AnyObject is not the ‘common 
>>> currency’ type for arbitrary Objective-C objects anymore.
>>> 
>>> I would like to propose we deprecate it as follows:
>>> 
>>> - Unconditional warning in Swift 4.1, with a fixit to add an ‘as’ cast to 
>>> cast the base value to the right type
>>> - Error in Swift 5 in -swift-version 5 mode
>>> 
>>> Thoughts? Does anyone actually rely on this feature, instead of just 
>>> stumbling on it by accident once in a while?
>>> 
>>> 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] Pitch: Member lookup on String should not find members of NSString

2017-10-24 Thread Slava Pestov via swift-evolution
Perhaps you could write up a proposal to outline the missing functionality :-)

Slava

> On Oct 24, 2017, at 3:09 PM, Jonathan Hull  wrote:
> 
> I would feel better about it if String gained a lot of the utility of 
> NSString (so that we don’t have to go to NSString all the time for methods)
> 
> Thanks,
> Jon
> 
>> On Oct 24, 2017, at 3:00 PM, Slava Pestov via swift-evolution 
>>  wrote:
>> 
>> Hi,
>> 
>> Members of NSString, except those defined in Foundation, are available on 
>> values of type String. For example,
>> 
>> extension NSString {
>> @objc func foo() {}
>> }
>> 
>> let s: String = “hello”
>> 
>> s.foo()
>> 
>> We don’t do this for any other bridged types, for instance NSArray methods 
>> are not imported as Array methods. It’s literally a special case in the type 
>> checker for member lookup on String.
>> 
>> This behavior doesn’t really much sense conceptually and it was put in as a 
>> stop-gap in Swift 1 to beef up the String API. I would like to phase it out 
>> as follows:
>> 
>> - Unconditional warning in Swift 4.1, with a fixit to insert an ‘as 
>> NSString’ cast
>> - Error in Swift 5 with -swift-version 5
>> 
>> What does everyone think about this?
>> 
>> Slava
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 

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


Re: [swift-evolution] Pitch: Deprecate/remove AnyObject method dispatch

2017-10-24 Thread Slava Pestov via swift-evolution
isEqual is defined on NSObject. You could also try using an array of 
AnyHashable and calling == instead of isEqual.

Slava

> On Oct 24, 2017, at 3:09 PM, Jon Shier  wrote:
> 
> Slava:
>   How would this change affect this code from Alamofire, used to compare 
> two SecKey instances for public key pinning:
> 
> outerLoop: for serverPublicKey in ServerTrustPolicy.publicKeys(for: 
> serverTrust) as [AnyObject] {
>for pinnedPublicKey in pinnedPublicKeys as [AnyObject] {
>if serverPublicKey.isEqual(pinnedPublicKey) {
>serverTrustIsValid = true
>break outerLoop
>}
>}
> }
> 
> I’m not sure why, but the AnyObject casting makes this work correctly, even 
> in Swift 4. I’ve tried to “modernize” it by using Sets (compare the pinned 
> keys with the available keys Sets) but it doesn’t work (hash implementation 
> for SecKey is weird?).  I’m guessing that with the AnyObject case and 
> isEqual, some underlying implementation is changed and equality works 
> properly (or well enough for this use). I’m happy to get rid of this hack, 
> but I’m not sure of any other method to accomplish our goals here.
> 
> 
> 
> Jon Shier
> 
>> On Oct 24, 2017, at 6:02 PM, Slava Pestov via swift-evolution 
>>  wrote:
>> 
>> Hi all,
>> 
>> Dynamic dispatch of methods through AnyObject is a source of implementation 
>> complexity, has many known bugs which we are not going to fix, and no longer 
>> makes sense now in an id-as-Any world; AnyObject is not the ‘common 
>> currency’ type for arbitrary Objective-C objects anymore.
>> 
>> I would like to propose we deprecate it as follows:
>> 
>> - Unconditional warning in Swift 4.1, with a fixit to add an ‘as’ cast to 
>> cast the base value to the right type
>> - Error in Swift 5 in -swift-version 5 mode
>> 
>> Thoughts? Does anyone actually rely on this feature, instead of just 
>> stumbling on it by accident once in a while?
>> 
>> 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] Pitch: Member lookup on String should not find members of NSString

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

Thanks,
Jon

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

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


Re: [swift-evolution] Pitch: Deprecate/remove AnyObject method dispatch

2017-10-24 Thread Jon Shier via swift-evolution
Slava:
How would this change affect this code from Alamofire, used to compare 
two SecKey instances for public key pinning:

outerLoop: for serverPublicKey in ServerTrustPolicy.publicKeys(for: 
serverTrust) as [AnyObject] {
for pinnedPublicKey in pinnedPublicKeys as [AnyObject] {
if serverPublicKey.isEqual(pinnedPublicKey) {
serverTrustIsValid = true
break outerLoop
}
}
}

I’m not sure why, but the AnyObject casting makes this work correctly, even in 
Swift 4. I’ve tried to “modernize” it by using Sets (compare the pinned keys 
with the available keys Sets) but it doesn’t work (hash implementation for 
SecKey is weird?).  I’m guessing that with the AnyObject case and isEqual, some 
underlying implementation is changed and equality works properly (or well 
enough for this use). I’m happy to get rid of this hack, but I’m not sure of 
any other method to accomplish our goals here.



Jon Shier

> On Oct 24, 2017, at 6:02 PM, Slava Pestov via swift-evolution 
>  wrote:
> 
> Hi all,
> 
> Dynamic dispatch of methods through AnyObject is a source of implementation 
> complexity, has many known bugs which we are not going to fix, and no longer 
> makes sense now in an id-as-Any world; AnyObject is not the ‘common currency’ 
> type for arbitrary Objective-C objects anymore.
> 
> I would like to propose we deprecate it as follows:
> 
> - Unconditional warning in Swift 4.1, with a fixit to add an ‘as’ cast to 
> cast the base value to the right type
> - Error in Swift 5 in -swift-version 5 mode
> 
> Thoughts? Does anyone actually rely on this feature, instead of just 
> stumbling on it by accident once in a while?
> 
> 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


[swift-evolution] Pitch: Deprecate/remove AnyObject method dispatch

2017-10-24 Thread Slava Pestov via swift-evolution
Hi all,

Dynamic dispatch of methods through AnyObject is a source of implementation 
complexity, has many known bugs which we are not going to fix, and no longer 
makes sense now in an id-as-Any world; AnyObject is not the ‘common currency’ 
type for arbitrary Objective-C objects anymore.

I would like to propose we deprecate it as follows:

- Unconditional warning in Swift 4.1, with a fixit to add an ‘as’ cast to cast 
the base value to the right type
- Error in Swift 5 in -swift-version 5 mode

Thoughts? Does anyone actually rely on this feature, instead of just stumbling 
on it by accident once in a while?

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


[swift-evolution] Pitch: Member lookup on String should not find members of NSString

2017-10-24 Thread Slava Pestov via swift-evolution
Hi,

Members of NSString, except those defined in Foundation, are available on 
values of type String. For example,

extension NSString {
  @objc func foo() {}
}

let s: String = “hello”

s.foo()

We don’t do this for any other bridged types, for instance NSArray methods are 
not imported as Array methods. It’s literally a special case in the type 
checker for member lookup on String.

This behavior doesn’t really much sense conceptually and it was put in as a 
stop-gap in Swift 1 to beef up the String API. I would like to phase it out as 
follows:

- Unconditional warning in Swift 4.1, with a fixit to insert an ‘as NSString’ 
cast
- Error in Swift 5 with -swift-version 5

What does everyone think about this?

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


[swift-evolution] [Pitch] Generic associatedtype subtype constraints

2017-10-24 Thread Rex Fenley via swift-evolution
Currently you can constrain a type parameter via a generic using equality

protocol A {
associatedtype T where T == BKind.V
associatedtype BKind: B
}

protocol B {
associatedtype V
}


However, you cannot do the following

associatedtype T where T: BKind.V

Could this be added to the language? Is there a reason something like this
would not be sound?

My use case would look like the following

protocol Mapping {
associatedtype MappedObject: DatabaseAdapterKind.BaseType
associatedtype DatabaseAdapterKind: DatabaseAdapter

...
}

protocol DatabaseAdapter {
associatedtype BaseType

...
}


For Realm Obj-C fulfillment would look like the following

// User is an RLMObject subtype

protocol UserMapping: Mapping {
typealias MappedObject = User
typealias DatabaseAdapterKind = RealmAdapter

// ... functions
}

protocol RealmAdapter: DatabaseAdapter {
typealias BaseType = RLMObject

// ... functions
}


For CoreData replace RLMObject with NSManagedObject

The mapping system allows the developer to write a mapping from JSON to a
type (MappedObject). Given that the type of MappedObject is a subtype of
the BaseType of the DatabaseAdapter the system will write an object of type
MappedObject to the database. This setup works with Realm Obj-C,
RealmSwift, and Core Data all of which have different BaseTypes but use
subtyping from a BaseType to specify the Model/MappedObject that is stored
in the db.

I can't use MappedObject == DatabaseAdapterKind.BaseType because this needs
to be a subtyping relation. E.g. a User: NSManagedObject is true but User
== NSManagedObject is not.

Since I can't specify this subtype relation in the protocol I end up having
to do runtime type checking and as! casts in quite a few places which seems
unnecessary and error prone during refactoring.

-- 

Rex Fenley  |  IOS DEVELOPER

Remind.com  |  BLOG 
 |  FOLLOW
US   |  LIKE US

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


Re: [swift-evolution] [draft] Introduce Sequence.filteredMap(_:)

2017-10-24 Thread Max Moiseev via swift-evolution


> On Oct 24, 2017, at 11:36 AM, Tino <2...@gmx.de> wrote:
> 
> 
>>> If the biggest problem of flatMap is that people who don’t understand it 
>>> write code that isn’t optimal (but still does the right thing!), I don’t 
>>> think there is any change needed. I’m not even sure that that 
>>> wrapping/unwrapping is actually done, because it should be discoverable by 
>>> the compiler.
>> It can be seen that the generated SIL is more complicated for a flatMap 
>> case, the microbenchmark also shows that it’s about 3x slower than the map. 
>> But even if that can be optimized away, don’t you find a String example from 
>> the proposal even a little convincing?
> It’s unfortunate when a piece of code gets a different meaning — but as you 
> said:
> It’s a misuse, and when you write code that is wrong, the results might be 
> wrong as well.
And this is exactly that we’re trying to address. Not the impurity of the 
function, not the performance, but the potential to misuse.
> 
> Maybe Scala chose better name for the concept, but the Swift definition is 
> consistent as it is now.
collect does not say anything about the transformation (A => B) that happens 
along the way…

> So, if you remove the third overload, the second one imho should be renamed, 
> too.
Honestly, I don’t see why. Can you elaborate? The second one is perfectly 
consistent, it does not mix two different functor instances in the same 
function.

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


Re: [swift-evolution] [draft] Introduce Sequence.filteredMap(_:)

2017-10-24 Thread Tino via swift-evolution

>> If the biggest problem of flatMap is that people who don’t understand it 
>> write code that isn’t optimal (but still does the right thing!), I don’t 
>> think there is any change needed. I’m not even sure that that 
>> wrapping/unwrapping is actually done, because it should be discoverable by 
>> the compiler.
> It can be seen that the generated SIL is more complicated for a flatMap case, 
> the microbenchmark also shows that it’s about 3x slower than the map. But 
> even if that can be optimized away, don’t you find a String example from the 
> proposal even a little convincing?
It’s unfortunate when a piece of code gets a different meaning — but as you 
said:
It’s a misuse, and when you write code that is wrong, the results might be 
wrong as well.

Maybe Scala chose better name for the concept, but the Swift definition is 
consistent as it is now.
So, if you remove the third overload, the second one imho should be renamed, 
too.___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2017-10-24 Thread Thorsten Seitz via swift-evolution

> Am 19.10.2017 um 22:49 schrieb Adam Kemp :
> 
>> 
>> On Oct 18, 2017, at 9:58 PM, Thorsten Seitz via swift-evolution 
>> > wrote:
>> 
>> In your earlier emails you wrote
>> 
>> "To make it concrete, say you write a function that just wraps map:
>> func firstNames(ofPeople people: Sequence) -> Sequence { 
>> return people.map { $0.firstName } } 
>>  I want that function to work on both ordered and unordered Sequences, and 
>> if you start with an ordered Sequence you should end up with an ordered 
>> Sequence. How do I make that work?"
>> Your example _won't work even today_ as `map` _returns an Array_ and _not_ a 
>> Sequence, like I have written several times now including in the very email 
>> you have been answering.
> 
> I guess it wouldn’t work exactly as written because Sequence isn’t generic 
> (why? I don’t know…)
> 
> Something like this is closer to what I was trying to describe:
> 
> func firstNames(ofPeople people:SeqPerson) -> AnySequence 
> where SeqPerson : Sequence, SeqPerson.Element : Person {
> return AnySequence(people.map { $0.firstName })
> }
> 
> (I shudder at how unnecessarily complex that is compared to .Net. I hope this 
> can be improved in the future, or that I am missing something that would make 
> it much simpler)
> 
> Since an array is a Sequence the (fixed) code above will work today with 
> either an Array or Set or any other Sequence of Person objects, and its 
> result can be fed into any function that takes in a Sequence of String.
> 
>> So you would just write the method with the most general argument type which 
>> is required by the method:
>> 
>> func firstNames(ofPeople people: Iterable) -> [String] {
>> return people.map { $0.firstName }
>> }
>> 
>> The return type would still be Array _just like today_.
> 
> Let me be clearer: I want my method firstNames(ofPeople:) to work on sets 
> just as it would work on any other Sequence. This method doesn’t care what 
> order things are in, but it also doesn’t alter the order so it is suitable 
> for use with both ordered and unordered inputs. Today I can write that 
> method, and it will work for a set or an array or anything else that conforms 
> to Sequence of Person, and it can then be chained with any other method that 
> operates on a Sequence of Person.
> 
> In order for your proposal to actually be effective you would need to change 
> map so that it doesn’t always give an ordered result. That means you would 
> have to make it not always return an array. The reason for that is that if 
> you left map alone then you could end up writing code like this:
> 
> var people:Set // comes from elsewhere
> var names:[String] // comes from elsewhere
> if (people.map { $0.firstName }.elementsEqual(names)) { // using the current 
> name
> // …
> }

I agree that `map` returning an Array is not a good solution (this applies for 
the current state as well) and it would make it decidedly too easy to move from 
unordered to ordered collections. So, you have a point there. Fixing this is 
still desirable even if not differentiating between unordered and ordered 
collections, though. This does require features which are currently planned 
like recursive protocol constraints on associated types (SR-1445, work on the 
implementation is already happening) and probably other features from the 
Generics Manifesto (which are highly desirable by themselves). 

-Thorsten


 
> 
> Notice how you start with an unordered input, but then map gives you an 
> array, which is ordered. Obviously map is useful to apply to sets so it would 
> have to continue accepting whatever protocol Set conforms to. If it still 
> returned Array regardless of the input type then it would convert an 
> unordered input into an ordered output, and that loses all of the benefits 
> you’re hoping to gain by having two types.
> 
> So clearly you would need map to not return Array when given an unordered 
> input. It’s important that you understand this. Without changing the return 
> type of map and other similar functions you have a huge hole in the type 
> system that loses most of the benefits you’re going for. You may as well not 
> do the feature if you’re not going to change this.
> 
> However, you also can’t just make map always return an unordered output type 
> because then if you started with an ordered input you would get an unordered 
> output, and that doesn’t make sense. That would be really tedious. So now you 
> need two implementations of map: one that takes an unordered input and gives 
> an unordered output, and another that takes an ordered input and returns an 
> ordered output.
> 
> Kevin was suggesting that you could make this easier to deal with by 
> introducing a new language feature, but it’s not clear exactly how that would 
> work, and I’m not convinced it would actually solve the problem I’ve 
> described.
> 
> This is what I mean when I said 

Re: [swift-evolution] [draft] Introduce Sequence.filteredMap(_:)

2017-10-24 Thread Max Moiseev via swift-evolution


> On Oct 23, 2017, at 8:38 PM, Howard Lovatt  wrote:
> 
> +1 good idea.
> 
> Re. the naming I would suggest `mapFilterNil` since it says what it does and 
> filter, nil, and map are all understood already in Swift. (I have sympathy 
> for people wanting `mapFilteringNil`, but Swift chose `filter`.)
`nil` is an overloaded term, since there is ExpressibleByNilLiteral, and pretty 
much any type can conform to it.

> 
> The problems I see with `filterMap` are that:
> 
>   1. It sounds like it is a merged `filter` and `map` and therefore you would 
> expect it to have two arguments, one to filter and one to map, i.e. 
> `filterMap(filter: (T) -> Bool, map: (T) -> R) -> [R]`.
>   2. It sounds like it will filter the incoming values (for `nil`, but see 1 
> above) and then map, i.e. `filterMap(map: (T?) -> R) -> [R]`, note `T?` 
> *not* `R?`.
> 
>   -- Howard.
> 
> On 24 October 2017 at 11:56, BJ Homer via swift-evolution 
> > wrote:
> I agree with Xiaodi; I like ‘filterMap’ more than ‘filteredMap’. But both are 
> superior to ‘flatMap’ in this context.
> 
> -BJ
> 
> On Oct 23, 2017, at 5:22 PM, Max Moiseev  > wrote:
> 
>> It occurred to me that filteringMap(_:) should be even more descriptive, 
>> still conform to the guidelines, although similarly unprecedented and 
>> un-googlable.
>> 
>> Max
>> 
>>> On Oct 23, 2017, at 3:52 PM, Xiaodi Wu >> > wrote:
>>> 
>>> +1 in general. As to the name: since 'map' is used as a term of art, 
>>> 'filterMap' seems superior to 'filteredMap', which half follows naming 
>>> guidelines and half is a term of art; neither is immediately comprehensible 
>>> but 'filterMap' can be googled and has precedents in other languages.
>>> On Mon, Oct 23, 2017 at 17:24 BJ Homer via swift-evolution 
>>> > wrote:
>>> I strongly agree! In fact, I just started writing up a similar proposal the 
>>> other day, but hadn’t had time to finish it yet.
>>> 
>>> The current name for this particular filtering variant is not particularly 
>>> descriptive. It’s certainly not obvious to newcomers that ‘flatMap’ will 
>>> filter out results. And it’s not true to the existing usage of ‘flatMap' 
>>> from other languages; you have to really squint at it to see how any 
>>> “flattening” is happening at all.
>>> 
>>> So yes, a big +1 from me. Thanks!
>>> 
>>> -BJ Homer
>>> 
 On Oct 23, 2017, at 4:15 PM, Max Moiseev via swift-evolution 
 > wrote:
 
 Hi swift-evolution!
 
 I would like to propose the following change to the standard library:
 
 deprecate `Sequence.flatMap(_: (Element) -> U?) -> [U]` and make this 
 functionality available under a new name `Sequence.filteredMap(_:)`.
 
 The draft is available at 
 https://gist.github.com/moiseev/2f36376c8ef4c2b1273cff0bfd9c3b95 
  and is 
 included below for your convenience.
 
 Max
 
 Introduce Sequence.filteredMap(_:)
 
 Proposal: SE- 
 Authors: Max Moiseev 
 Review Manager: TBD
 Status: Awaiting implementation
  
 Introduction
 
 We propose to deprecate the controversial version of a Sequence.flatMap 
 method and provide the same functionality under a different, and 
 potentially more descriptive, name.
 
  
 Motivation
 
 The Swift standard library currently defines 3 distinct overloads for 
 flatMap:
 
 Sequence.flatMap(_: (Element) -> S) -> [S.Element]
 where S : Sequence
 Optional.flatMap(_: (Wrapped) -> U?) -> U?
 Sequence.flatMap(_: (Element) -> U?) -> [U]
 The last one, despite being useful in certain situations, can be (and 
 often is) misused. Consider the following snippet:
 
 struct Person {
   var age: Int
   var name: String
 }
 
 func getAges(people: [Person]) -> [Int] {
   return people.flatMap { $0.age }
 }
 What happens inside getNames is: thanks to the implicit promotion to 
 Optional, the result of the closure gets wrapped into a .some, then 
 immediately unwrapped by the implementation of flatMap, and appended to 
 the result array. All this unnecessary wrapping and unwrapping can be 
 easily avoided by just using map instead.
 
 func getAges(people: [Person]) -> [Int] {
   return people.map { $0.age }
 }
 It gets even worse when we consider future code modifications, like the 
 one where 

Re: [swift-evolution] Opaque Pointers in Swift

2017-10-24 Thread Cory Benfield via swift-evolution


> On 24 Oct 2017, at 18:11, Félix Cloutier  wrote:
> 
> Could you do a conditional typealias?

I don’t *think* so. In the case of OpenSSL the #define you want to use is 
OPENSSL_VERSION_NUMBER, which is defined in an OpenSSL header file. As far as I 
know, the Swift compiler does not see #defines from C header files when 
compiling Swift code (some experimenting suggests that this is still true, 
though I am not *certain* of that).

That would mean we’d have to pass this as a build flag with -D, which doesn’t 
really work with distribution via SwiftPM, and also would require that users 
know that this flag needs to be passed for newer OpenSSLs.

Cory

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


Re: [swift-evolution] Opaque Pointers in Swift

2017-10-24 Thread Johannes Weiß via swift-evolution
Hi Cory,

I think we're dealing with two separate issues here.

1) that all forward declared struct pointers get imported as an OpaquePointer 
which makes us lose all type-safety
2) that it's a fairly frequent case that C libraries evolve from 'pointers to 
fully declared structs' to 'pointers to forward declared structs'


Regarding 1)

I fully agree that is pretty bad and I believe I have an idea what the Swift 
importer should do for that case:

For the following C types

struct foo_s;
typedef foo_s *foo;

struct bar_s;
typedef bar_s *bar;

the C compiler today imports both `foo` and `bar` as `OpaquePointer` which 
isn't very helpful. Instead I believe the importer should declare to phantom 
types

enum foo_s {}
enum bar_s {}

and import `foo` as `typealias foo = OpaquePointer` and `bar` as 
`typealias bar = OpaquePointer`.

That seems to preserve the right semantics:

 - we can't have any values of `foo_s` or `bar_s` as they're phantom
 - we can however have pointers to them
 - in this example the pointers are `OpaquePointer` and 
`OpaquePointer`, deliberately not `UnsafePointer` and 
`UnsafePointer` so we don't have an issue that the user can do 
'unsafePtr.pointee'

How do people think about this proposed change?

Regarding 2)


I feel you'd prefer if we'd import the above as `typealias foo = 
UnsafePointer` which I would be happy with but I can also see why 
`OpaquePointer` exists: It stops us from dereferencing the pointer at compile 
time (just like C does).

So yes, I agree we should fix (1). For the time being I believe I have 
something that might work for you use-case even today (and would work even 
nicer if the above changes are implemented):

Today, we already have the following initialisers

struct UnsafePointer {
init?(_ ptr: OpaquePointer)
}

and

struct OpaquePointer {
init?(_ ptr: UnsafePointer)
}

by just adding the following two trivial ones:

extension UnsafePointer {
init?(_ ptr: UnsafePointer) { return ptr }
}
extension OpaquePointer {
init?(_ ptr: OpaquePointer) { return ptr }
}

this should solve your problem:

- when you receive a pointer from the C library, store it as OpaquePointer
let myOpaquePointer: OpaquePointer = 
OpaquePointer(c_library_create_function())
  which now should work regardless of whether you're linking the old or the new 
version of the C library
- when you pass a pointer to the C library:
c_library_consuming_function(.init(myOpaquePointer))
  which should (modulo it doesn't right now 
https://bugs.swift.org/browse/SR-6211) select the right initialiser for you, 
only it doesn't 

But fortunately we can work around it:

--- SNIP ---
extension UnsafePointer {
static func make(_ ptr: UnsafePointer) -> UnsafePointer {
return ptr
}
static func make(_ ptr: OpaquePointer) -> UnsafePointer {
return UnsafePointer(ptr)
}
}
extension OpaquePointer {
static func make(_ ptr: UnsafePointer) -> OpaquePointer {
return OpaquePointer(ptr)!
}
static func make(_ ptr: OpaquePointer) -> OpaquePointer {
return ptr
}
}

func mockCLibraryCreateOld() -> UnsafePointer {
return UnsafePointer(UnsafeMutablePointer.allocate(capacity: 1))
}

func mockCLibraryCreateNew() -> OpaquePointer {
return OpaquePointer(mockCLibraryCreateOld())
}

func mockCLibraryConsumeOld(_ x: UnsafePointer) {}
func mockCLibraryConsumeNew(_ x: OpaquePointer) {}


let fromCold: OpaquePointer = .make(mockCLibraryCreateOld())
let fromCnew: OpaquePointer = .make(mockCLibraryCreateNew())

mockCLibraryConsumeOld(.make(fromCold))
mockCLibraryConsumeNew(.make(fromCnew))
mockCLibraryConsumeOld(.make(fromCnew))
mockCLibraryConsumeNew(.make(fromCold))
--- SNAP ---

HTH

-- Johannes



> On 24 Oct 2017, at 9:14 am, Cory Benfield via swift-evolution 
>  wrote:
> 
> I wanted to discuss a recent difficulty I’ve encountered while writing a 
> Swift program that uses a C library that has recently changed its API to use 
> opaque pointers, with an eye towards asking whether there are suggestions for 
> ways to tackle the problem that I haven’t considered, or whether some 
> enhancement to Swift should be proposed to provide a solution.
> 
> A common trend in modern C code is to encapsulate application data by using 
> pointers to “opaque” data structures: that is, data structures whose complete 
> definition is not available in the header files for the library. This has 
> many benefits from the perspective of library developers, mostly notably 
> because it limits the ABI of the library, making it easier to change the 
> internals without requiring recompilation or breaking changes. Pointers to 
> these structures are translated into Swift code in the form of the 
> OpaquePointer type.
> 
> Older C libraries frequently have non-opaque structures: that is, the 
> structure definition is available in the header files for the library. When 
> using code like 

Re: [swift-evolution] Opaque Pointers in Swift

2017-10-24 Thread Félix Cloutier via swift-evolution
Could you do a conditional typealias?

#if OPENSSL_HAS_OPAQUE_POINTERS
typealias OpenSSLContext = OpaquePointer
#else
typealias OpenSSLContext = UnsafeMutablePointer
#endif

Then as long as you don't need to build one single OpenSSL that supports both, 
you'll be fine (although it might work anyway, I think).

A problem with OpaquePointer is that it forces T into existence. Swift 
doesn't have a notion of an incomplete type: if you write "struct foo;" in a 
header and bridge it to Swift, no "foo" type is imported. And of course, if 
it's supported, you shouldn't be able to instantiate one, and you shouldn't be 
able to get a type of pointer that is not an OpaquePointer to them, because 
you'd be able to dereference them. (Maybe they could be imported as enums with 
no cases? That's how we've been doing inconstructible types so far. Not sure if 
it would have strange implications.)

Félix

> Le 24 oct. 2017 à 01:14, Cory Benfield via swift-evolution 
>  a écrit :
> 
> I wanted to discuss a recent difficulty I’ve encountered while writing a 
> Swift program that uses a C library that has recently changed its API to use 
> opaque pointers, with an eye towards asking whether there are suggestions for 
> ways to tackle the problem that I haven’t considered, or whether some 
> enhancement to Swift should be proposed to provide a solution.
> 
> A common trend in modern C code is to encapsulate application data by using 
> pointers to “opaque” data structures: that is, data structures whose complete 
> definition is not available in the header files for the library. This has 
> many benefits from the perspective of library developers, mostly notably 
> because it limits the ABI of the library, making it easier to change the 
> internals without requiring recompilation or breaking changes. Pointers to 
> these structures are translated into Swift code in the form of the 
> OpaquePointer type.
> 
> Older C libraries frequently have non-opaque structures: that is, the 
> structure definition is available in the header files for the library. When 
> using code like this from Swift, pointers to these structures are translated 
> to Unsafe[Mutable]Pointer.
> 
> Both of these cases are well-handled by Swift today: opaque pointers 
> correctly can do absolutely nothing, whereas typed pointers have the option 
> of having behaviour based on knowing about the size of the data structure to 
> which they point. All very good.
> 
> A problem arises if a C dependency chooses to transition from non-opaque to 
> opaque structures. This is a transition that well-maintained C libraries are 
> strongly incentivised to make, but if you want to write Swift code that will 
> compile against both the old and new version of the library you run into 
> substantial issues. To illustrate the issue I’ll construct a small problem 
> based on the most widely-used library to recently make this transition, 
> OpenSSL.
> 
> In OpenSSL 1.1.0 almost all of the previously-open data structures were made 
> opaque, including the heavily used SSL_CTX structure. In terms of C code, the 
> header file declaration changed from 
> 
> 
>   struct ssl_ctx_st {
>   const SSL_METHOD *method;
>   // snip 250 lines of structure declaration
>   }
>   typedef struct ssl_ctx_st SSL_CTX;
> 
> to
> 
>   typedef struct ssl_ctx_st SSL_CTX;
> 
> 
> At an API level, any function that worked on the SSL_CTX structure that 
> existed before this change was unaffected. For example, the function 
> SSL_CTX_use_certificate has the same C API in both versions:
> 
>   int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x);
> 
> Unfortunately, in Swift the API for this function changes dramatically, from 
> 
>   func SSL_CTX_use_certificate(_ ctx: UnsafeMutablePointer!,
> _ x: 
> UnsafeMutablePointer!) -> Int32
> 
> to
> 
>   func SSL_CTX_use_certificate(_ ctx: OpaquePointer!,
> _ x: OpaquePointer!) 
> -> Int32
> 
> The reason this is problematic is that there is no implicit cast in either 
> direction between UnsafeMutablePointer and OpaquePointer. This means the 
> API here has changed in an incompatible way: types that are valid before the 
> structure was made opaque are not valid afterwards. This adds a pretty 
> substantial burden to supporting multiple versions of the same library from 
> Swift code.
> 
> So far I have thought of the following solutions to this problem that I can 
> implement today:
> 
> 1. Write a C wrapper library that exposes a third, consistent type that is 
> the same on all versions. Most likely this would be done by re-exposing all 
> these methods with arguments that take `void *` and performing the cast in C 
> code. This, unfortunately, loses some of the Swift compiler’s ability to 
> enforce type safety, as all these arguments will now be UnsafeRawPointer. 
> 

Re: [swift-evolution] [draft] Introduce Sequence.filteredMap(_:)

2017-10-24 Thread Max Moiseev via swift-evolution


> On Oct 24, 2017, at 5:10 AM, Tino <2...@gmx.de> wrote:
> 
> 
>> Calling "flatMap" a map + filtering out the nil values was a TERRIBLE idea.
> maybe I’m the one who’s getting this all wrong, but afaik the purpose of 
> flatMap isn’t filtering out nil at all, but just a combination of map & 
> flatten…
> Optional is like Array with a maximal capacity of one (so it can either 
> contain a single object, or it’s empty), and in this interpretation, there’s 
> nothing wrong with the behavior.

> 
> Instead, I think Nobuo Saito is right, and that a renaming to filteredMap is 
> only fighting symptoms, and not the cause (but I’m not that sure if there’s a 
> good way to tackle the cause).
> Besides that, all those alternative names also have potential for confusion:
> Imho it isn’t intuitive what is filtered out — and don’t forget that the 
> result of flatMap can contain nil elements…
> 
> If the biggest problem of flatMap is that people who don’t understand it 
> write code that isn’t optimal (but still does the right thing!), I don’t 
> think there is any change needed. I’m not even sure that that 
> wrapping/unwrapping is actually done, because it should be discoverable by 
> the compiler.
It can be seen that the generated SIL is more complicated for a flatMap case, 
the microbenchmark also shows that it’s about 3x slower than the map. But even 
if that can be optimized away, don’t you find a String example from the 
proposal even a little convincing?
> 
> It would be nice if there was an way to warn in places where flatMap could be 
> replaced with map, though (but imho this special warning shouldn’t be checked 
> by the compiler).
I tried to avoid renaming: https://github.com/apple/swift/pull/7823/ 
 but then 
https://github.com/apple/swift/pull/9390 
.
> 
> - Tino

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


Re: [swift-evolution] [draft] Introduce Sequence.filteredMap(_:)

2017-10-24 Thread Matthew Johnson via swift-evolution

> On Oct 24, 2017, at 1:57 AM, David Hart via swift-evolution 
>  wrote:
> 
> I also cast my vote for filterMap. It’s concise, understandable and is kind 
> of a term of art also.

+1.  This seems like the best option to me.

> 
>> On 24 Oct 2017, at 02:56, BJ Homer via swift-evolution 
>> > wrote:
>> 
>> I agree with Xiaodi; I like ‘filterMap’ more than ‘filteredMap’. But both 
>> are superior to ‘flatMap’ in this context.
>> 
>> -BJ
>> 
>> On Oct 23, 2017, at 5:22 PM, Max Moiseev > > wrote:
>> 
>>> It occurred to me that filteringMap(_:) should be even more descriptive, 
>>> still conform to the guidelines, although similarly unprecedented and 
>>> un-googlable.
>>> 
>>> Max
>>> 
 On Oct 23, 2017, at 3:52 PM, Xiaodi Wu > wrote:
 
 +1 in general. As to the name: since 'map' is used as a term of art, 
 'filterMap' seems superior to 'filteredMap', which half follows naming 
 guidelines and half is a term of art; neither is immediately 
 comprehensible but 'filterMap' can be googled and has precedents in other 
 languages.
 On Mon, Oct 23, 2017 at 17:24 BJ Homer via swift-evolution 
 > wrote:
 I strongly agree! In fact, I just started writing up a similar proposal 
 the other day, but hadn’t had time to finish it yet.
 
 The current name for this particular filtering variant is not particularly 
 descriptive. It’s certainly not obvious to newcomers that ‘flatMap’ will 
 filter out results. And it’s not true to the existing usage of ‘flatMap' 
 from other languages; you have to really squint at it to see how any 
 “flattening” is happening at all.
 
 So yes, a big +1 from me. Thanks!
 
 -BJ Homer
 
> On Oct 23, 2017, at 4:15 PM, Max Moiseev via swift-evolution 
> > wrote:
> 
> Hi swift-evolution!
> 
> I would like to propose the following change to the standard library:
> 
> deprecate `Sequence.flatMap(_: (Element) -> U?) -> [U]` and make this 
> functionality available under a new name `Sequence.filteredMap(_:)`.
> 
> The draft is available at 
> https://gist.github.com/moiseev/2f36376c8ef4c2b1273cff0bfd9c3b95 
>  and is 
> included below for your convenience.
> 
> Max
> 
> Introduce Sequence.filteredMap(_:)
> 
> Proposal: SE- 
> Authors: Max Moiseev 
> Review Manager: TBD
> Status: Awaiting implementation
>  
> Introduction
> 
> We propose to deprecate the controversial version of a Sequence.flatMap 
> method and provide the same functionality under a different, and 
> potentially more descriptive, name.
> 
>  
> Motivation
> 
> The Swift standard library currently defines 3 distinct overloads for 
> flatMap:
> 
> Sequence.flatMap(_: (Element) -> S) -> [S.Element]
> where S : Sequence
> Optional.flatMap(_: (Wrapped) -> U?) -> U?
> Sequence.flatMap(_: (Element) -> U?) -> [U]
> The last one, despite being useful in certain situations, can be (and 
> often is) misused. Consider the following snippet:
> 
> struct Person {
>   var age: Int
>   var name: String
> }
> 
> func getAges(people: [Person]) -> [Int] {
>   return people.flatMap { $0.age }
> }
> What happens inside getNames is: thanks to the implicit promotion to 
> Optional, the result of the closure gets wrapped into a .some, then 
> immediately unwrapped by the implementation of flatMap, and appended to 
> the result array. All this unnecessary wrapping and unwrapping can be 
> easily avoided by just using map instead.
> 
> func getAges(people: [Person]) -> [Int] {
>   return people.map { $0.age }
> }
> It gets even worse when we consider future code modifications, like the 
> one where Swift 4 introduced a Stringconformance to the Collection 
> protocol. The following code used to compile (due to the flatMap overload 
> in question).
> 
> func getNames(people: [Person]) -> [String] {
>   return people.flatMap { $0.name }
> }
> But it no longer does, because now there is a better overload that does 
> not involve implicit promotion. In this particular case, the compiler 
> error would be obvious, as it would point at the same line where flatMap 
> is used. Imagine however 

Re: [swift-evolution] [SPM] Roadmap?

2017-10-24 Thread David James via swift-evolution
I would also +1000 Xcode integration, whoever does it. I’m tired of fighting 
with command-line mumbo jumbo just to setup and manage dependencies. SPM should 
pave the way for high-level or junior devs to easily handle their dependencies 
in the IDE of their choice.

> On 24 Oct 2017, at 13:46, Adrian Kashivskyy via swift-evolution 
>  wrote:
> 
> I would like Xcode integration 
> 
> The last thing I want from a platform-agnostic open-source package manager is 
> built-in integration with a single-platform commercial closed-source IDE. 
> 
> I think this should be done independently by DT team, without any special 
> favouritism by SPM.
> 
> ——
> Adrian Kashivskyy
> 
> On 23 Oct 2017, 19:41 +0200, Jean-Christophe Pastant via swift-evolution 
> , wrote:
>> Hi,
>> 
>> Is there any news about features that are willling to be integrated into SPM 
>> 5?
>> Those I see the most relevant:
>> - iOS support
>> - Some kind of configuration/settings support (debug, release, ...)
>> 
>> I'd like to hear about it from maintainers, especially if there's a priority 
>> order we should follow.
>> 
>> Regards,
>> 
>> 
>> ___
>> 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

David James

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


Re: [swift-evolution] [draft] Introduce Sequence.filteredMap(_:)

2017-10-24 Thread Elviro Rocca via swift-evolution
"Flattening" in the context of functional programming (and that's where map and 
flatMap come from) means something like this:

F -> F

So for example:

Array -> Array

or

Optional -> Optional

but NOT:

Array -> Array

It's simply the wrong word for the operation.

If "Map" is something like this:

(F + (T -> U)) -> F

then "FlatMap" means "map to the same functor, then flatten", thus:

(F + (A -> F)) -> F
then 
(F -> F)

In this case "U == F"

In fact, there's (rightfully) a FlatMap method on Optional in cases in which 
the mapping function produces another Optional (notice that the chained 
unwrapping with "?." is a FlatMap operation).

Calling FlatMap something that is not (in the literature and community at 
large) was not a good idea, in my opinion.

Elviro

> Il giorno 24 ott 2017, alle ore 14:10, Tino <2...@gmx.de> ha scritto:
> 
> 
>> Calling "flatMap" a map + filtering out the nil values was a TERRIBLE idea.
> maybe I’m the one who’s getting this all wrong, but afaik the purpose of 
> flatMap isn’t filtering out nil at all, but just a combination of map & 
> flatten…
> Optional is like Array with a maximal capacity of one (so it can either 
> contain a single object, or it’s empty), and in this interpretation, there’s 
> nothing wrong with the behavior.
> 
> Instead, I think Nobuo Saito is right, and that a renaming to filteredMap is 
> only fighting symptoms, and not the cause (but I’m not that sure if there’s a 
> good way to tackle the cause).
> Besides that, all those alternative names also have potential for confusion:
> Imho it isn’t intuitive what is filtered out — and don’t forget that the 
> result of flatMap can contain nil elements…
> 
> If the biggest problem of flatMap is that people who don’t understand it 
> write code that isn’t optimal (but still does the right thing!), I don’t 
> think there is any change needed. I’m not even sure that that 
> wrapping/unwrapping is actually done, because it should be discoverable by 
> the compiler.
> 
> It would be nice if there was an way to warn in places where flatMap could be 
> replaced with map, though (but imho this special warning shouldn’t be checked 
> by the compiler).
> 
> - Tino

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


Re: [swift-evolution] [SPM] Roadmap?

2017-10-24 Thread David Hart via swift-evolution
I think what Howard Lovatt and others are hoping is for SwiftPM to add the few 
platform-agnostic features which are necessary for the DT team to integrate it 
as a first-class dependency solution for iOS projects in Xcode (build settings, 
bundle assets, etc…).

> On 24 Oct 2017, at 13:46, Adrian Kashivskyy via swift-evolution 
>  wrote:
> 
> I would like Xcode integration 
> 
> The last thing I want from a platform-agnostic open-source package manager is 
> built-in integration with a single-platform commercial closed-source IDE. 
> 
> I think this should be done independently by DT team, without any special 
> favouritism by SPM.
> 
> ——
> Adrian Kashivskyy
> 
> On 23 Oct 2017, 19:41 +0200, Jean-Christophe Pastant via swift-evolution 
> , wrote:
>> Hi,
>> 
>> Is there any news about features that are willling to be integrated into SPM 
>> 5?
>> Those I see the most relevant:
>> - iOS support
>> - Some kind of configuration/settings support (debug, release, ...)
>> 
>> I'd like to hear about it from maintainers, especially if there's a priority 
>> order we should follow.
>> 
>> Regards,
>> 
>> 
>> ___
>> 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] [draft] Introduce Sequence.filteredMap(_:)

2017-10-24 Thread Tino via swift-evolution

> Calling "flatMap" a map + filtering out the nil values was a TERRIBLE idea.
maybe I’m the one who’s getting this all wrong, but afaik the purpose of 
flatMap isn’t filtering out nil at all, but just a combination of map & flatten…
Optional is like Array with a maximal capacity of one (so it can either 
contain a single object, or it’s empty), and in this interpretation, there’s 
nothing wrong with the behavior.

Instead, I think Nobuo Saito is right, and that a renaming to filteredMap is 
only fighting symptoms, and not the cause (but I’m not that sure if there’s a 
good way to tackle the cause).
Besides that, all those alternative names also have potential for confusion:
Imho it isn’t intuitive what is filtered out — and don’t forget that the result 
of flatMap can contain nil elements…

If the biggest problem of flatMap is that people who don’t understand it write 
code that isn’t optimal (but still does the right thing!), I don’t think there 
is any change needed. I’m not even sure that that wrapping/unwrapping is 
actually done, because it should be discoverable by the compiler.

It would be nice if there was an way to warn in places where flatMap could be 
replaced with map, though (but imho this special warning shouldn’t be checked 
by the compiler).

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


Re: [swift-evolution] [SPM] Roadmap?

2017-10-24 Thread Adrian Kashivskyy via swift-evolution
> I would like Xcode integration 

The last thing I want from a platform-agnostic open-source package manager is 
built-in integration with a single-platform commercial closed-source IDE. 

I think this should be done independently by DT team, without any special 
favouritism by SPM.

——
Adrian Kashivskyy

On 23 Oct 2017, 19:41 +0200, Jean-Christophe Pastant via swift-evolution 
, wrote:
> Hi,
>
> Is there any news about features that are willling to be integrated into SPM 
> 5?
> Those I see the most relevant:
> - iOS support
> - Some kind of configuration/settings support (debug, release, ...)
>
> I'd like to hear about it from maintainers, especially if there's a priority 
> order we should follow.
>
> Regards,
>
>
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [draft] Introduce Sequence.filteredMap(_:)

2017-10-24 Thread Adrian Kashivskyy via swift-evolution
+1 from me as well.

——
Adrian Kashivskyy

On 24 Oct 2017, 00:24 +0200, BJ Homer via swift-evolution 
, wrote:
> I strongly agree! In fact, I just started writing up a similar proposal the 
> other day, but hadn’t had time to finish it yet.
>
> The current name for this particular filtering variant is not particularly 
> descriptive. It’s certainly not obvious to newcomers that ‘flatMap’ will 
> filter out results. And it’s not true to the existing usage of ‘flatMap' from 
> other languages; you have to really squint at it to see how any “flattening” 
> is happening at all.
>
> So yes, a big +1 from me. Thanks!
>
> -BJ Homer
>
> > On Oct 23, 2017, at 4:15 PM, Max Moiseev via swift-evolution 
> >  wrote:
> >
> > Hi swift-evolution!
> >
> > I would like to propose the following change to the standard library:
> >
> > deprecate `Sequence.flatMap(_: (Element) -> U?) -> [U]` and make this 
> > functionality available under a new name `Sequence.filteredMap(_:)`.
> >
> > The draft is available at 
> > https://gist.github.com/moiseev/2f36376c8ef4c2b1273cff0bfd9c3b95 and is 
> > included below for your convenience.
> >
> > Max
> >
> > Introduce Sequence.filteredMap(_:)
> >
> > • Proposal: SE-
> > • Authors: Max Moiseev
> > • Review Manager: TBD
> > • Status: Awaiting implementation
> >
> > Introduction
> > We propose to deprecate the controversial version of a Sequence.flatMap 
> > method and provide the same functionality under a different, and 
> > potentially more descriptive, name.
> > Motivation
> > The Swift standard library currently defines 3 distinct overloads for 
> > flatMap:
> > Sequence.flatMap(_: (Element) -> S) -> [S.Element]
> >where S : Sequence
> > Optional.flatMap(_: (Wrapped) -> U?) -> U?
> > Sequence.flatMap(_: (Element) -> U?) -> [U]
> > The last one, despite being useful in certain situations, can be (and often 
> > is) misused. Consider the following snippet:
> > struct Person {
> > var age: Int
> > var name: String
> > }
> >
> > func getAges(people: [Person]) -> [Int] {
> > return people.flatMap { $0.age }
> > }
> > What happens inside getNames is: thanks to the implicit promotion to 
> > Optional, the result of the closure gets wrapped into a .some, then 
> > immediately unwrapped by the implementation of flatMap, and appended to the 
> > result array. All this unnecessary wrapping and unwrapping can be easily 
> > avoided by just using map instead.
> > func getAges(people: [Person]) -> [Int] {
> > return people.map { $0.age }
> > }
> > It gets even worse when we consider future code modifications, like the one 
> > where Swift 4 introduced a Stringconformance to the Collection protocol. 
> > The following code used to compile (due to the flatMap overload in 
> > question).
> > func getNames(people: [Person]) -> [String] {
> > return people.flatMap { $0.name }
> > }
> > But it no longer does, because now there is a better overload that does not 
> > involve implicit promotion. In this particular case, the compiler error 
> > would be obvious, as it would point at the same line where flatMap is used. 
> > Imagine however if it was just a let names = people.flatMap { $0.name } 
> > statement, and the names variable were used elsewhere. The compiler error 
> > would be misleading.
> > Proposed solution
> > We propose to deprecate the controversial overload of flatMap and 
> > re-introduce the same functionality under a new name. The name being 
> > filteredMap(_:) as we believe it best describes the intent of this function.
> > For reference, here are the alternative names from other languages:
> >
> > • Haskell, Idris  mapMaybe :: (a -> Maybe b) -> [a] -> [b]
> > • Ocaml (Core and Batteries)  filter_map : 'a t -> f:('a -> 'b option) -> 
> > 'b t
> > • F#  List.choose : ('T -> 'U option) -> 'T list -> 'U list
> > • Rust  fn filter_map(self, f: F) -> FilterMap where F: 
> > FnMut(Self::Item) -> Option
> > • Scala  def collect[B](pf: PartialFunction[A, B]): List[B]
> >
> > Source compatibility
> > Since the old function will still be available (although deprecated) all 
> > the existing code will compile, producing a deprecation warning and a 
> > fix-it.
> > Effect on ABI stability
> > This is an additive API change, and does not affect ABI stability.
> > Effect on API resilience
> > Ideally, the deprecated flatMap overload would not exist at the time when 
> > ABI stability is declared, but in the worst case, it will be available in a 
> > deprecated form from a library post-ABI stability.
> > Alternatives considered
> > It was attempted in the past to warn about this kind of misuse and do the 
> > right thing instead by means of a deprecated overload with a 
> > non-optional-returning closure. The attempt failed due to another implicit 
> > promotion (this time to Any).
> > The following alternative names for this function were considered:
> >
> > • mapNonNil(_:)  Does not communicate what happens to nil’s
> > • 

Re: [swift-evolution] [draft] Introduce Sequence.filteredMap(_:)

2017-10-24 Thread Elviro Rocca via swift-evolution
Huge +1

Calling "flatMap" a map + filtering out the nil values was a TERRIBLE idea.


Elviro

> Il giorno 24 ott 2017, alle ore 00:15, Max Moiseev via swift-evolution 
>  ha scritto:
> 
> Hi swift-evolution!
> 
> I would like to propose the following change to the standard library:
> 
> deprecate `Sequence.flatMap(_: (Element) -> U?) -> [U]` and make this 
> functionality available under a new name `Sequence.filteredMap(_:)`.
> 
> The draft is available at 
> https://gist.github.com/moiseev/2f36376c8ef4c2b1273cff0bfd9c3b95 
>  and is 
> included below for your convenience.
> 
> Max
> 
> Introduce Sequence.filteredMap(_:)
> 
> Proposal: SE- 
> Authors: Max Moiseev 
> Review Manager: TBD
> Status: Awaiting implementation
>  
> Introduction
> 
> We propose to deprecate the controversial version of a Sequence.flatMap 
> method and provide the same functionality under a different, and potentially 
> more descriptive, name.
> 
>  
> Motivation
> 
> The Swift standard library currently defines 3 distinct overloads for flatMap:
> 
> Sequence.flatMap(_: (Element) -> S) -> [S.Element]
> where S : Sequence
> Optional.flatMap(_: (Wrapped) -> U?) -> U?
> Sequence.flatMap(_: (Element) -> U?) -> [U]
> The last one, despite being useful in certain situations, can be (and often 
> is) misused. Consider the following snippet:
> 
> struct Person {
>   var age: Int
>   var name: String
> }
> 
> func getAges(people: [Person]) -> [Int] {
>   return people.flatMap { $0.age }
> }
> What happens inside getNames is: thanks to the implicit promotion to 
> Optional, the result of the closure gets wrapped into a .some, then 
> immediately unwrapped by the implementation of flatMap, and appended to the 
> result array. All this unnecessary wrapping and unwrapping can be easily 
> avoided by just using map instead.
> 
> func getAges(people: [Person]) -> [Int] {
>   return people.map { $0.age }
> }
> It gets even worse when we consider future code modifications, like the one 
> where Swift 4 introduced a Stringconformance to the Collection protocol. The 
> following code used to compile (due to the flatMap overload in question).
> 
> func getNames(people: [Person]) -> [String] {
>   return people.flatMap { $0.name }
> }
> But it no longer does, because now there is a better overload that does not 
> involve implicit promotion. In this particular case, the compiler error would 
> be obvious, as it would point at the same line where flatMap is used. Imagine 
> however if it was just a let names = people.flatMap { $0.name } statement, 
> and the names variable were used elsewhere. The compiler error would be 
> misleading.
> 
>  
> Proposed
>  solution
> 
> We propose to deprecate the controversial overload of flatMap and 
> re-introduce the same functionality under a new name. The name being 
> filteredMap(_:) as we believe it best describes the intent of this function.
> 
> For reference, here are the alternative names from other languages:
> 
> Haskell, Idris 
> mapMaybe :: (a -> Maybe b) -> [a] -> [b]
> Ocaml (Core and Batteries)
>  filter_map : 'a t -> f:('a -> 'b option) -> 'b t
> F#
>  List.choose : ('T -> 'U option) -> 'T list -> 'U list
> Rust
>  fn filter_map(self, f: F) -> FilterMap
>  where F: 
> FnMut(Self::Item) -> Option
> Scala 
> def collect[B](pf: PartialFunction[A, B]): List[B]
>  
> Source
>  compatibility
> 
> Since the old function will still be available (although deprecated) all the 
> existing code will compile, producing a deprecation warning and a fix-it.
> 
>  
> Effect
>  on ABI stability
> 
> This is an additive API change, and does not affect ABI stability.
> 
>  
> Effect
>  on API resilience
> 
> Ideally, the deprecated flatMap overload would not exist at the time when ABI 
> stability is declared, but in the worst case, it will be available in a 
> deprecated form from a library post-ABI stability.
> 
>  
> Alternatives
>  considered
> 
> It was attempted in the past to warn about this kind of misuse and do the 
> right thing instead by means of a deprecated overload with a 
> non-optional-returning closure. The attempt failed due to another implicit 
> promotion (this time to Any).
> 
> The following alternative names for this 

[swift-evolution] Opaque Pointers in Swift

2017-10-24 Thread Cory Benfield via swift-evolution
I wanted to discuss a recent difficulty I’ve encountered while writing a Swift 
program that uses a C library that has recently changed its API to use opaque 
pointers, with an eye towards asking whether there are suggestions for ways to 
tackle the problem that I haven’t considered, or whether some enhancement to 
Swift should be proposed to provide a solution.

A common trend in modern C code is to encapsulate application data by using 
pointers to “opaque” data structures: that is, data structures whose complete 
definition is not available in the header files for the library. This has many 
benefits from the perspective of library developers, mostly notably because it 
limits the ABI of the library, making it easier to change the internals without 
requiring recompilation or breaking changes. Pointers to these structures are 
translated into Swift code in the form of the OpaquePointer type.

Older C libraries frequently have non-opaque structures: that is, the structure 
definition is available in the header files for the library. When using code 
like this from Swift, pointers to these structures are translated to 
Unsafe[Mutable]Pointer.

Both of these cases are well-handled by Swift today: opaque pointers correctly 
can do absolutely nothing, whereas typed pointers have the option of having 
behaviour based on knowing about the size of the data structure to which they 
point. All very good.

A problem arises if a C dependency chooses to transition from non-opaque to 
opaque structures. This is a transition that well-maintained C libraries are 
strongly incentivised to make, but if you want to write Swift code that will 
compile against both the old and new version of the library you run into 
substantial issues. To illustrate the issue I’ll construct a small problem 
based on the most widely-used library to recently make this transition, OpenSSL.

In OpenSSL 1.1.0 almost all of the previously-open data structures were made 
opaque, including the heavily used SSL_CTX structure. In terms of C code, the 
header file declaration changed from 


struct ssl_ctx_st {
const SSL_METHOD *method;
// snip 250 lines of structure declaration
}
typedef struct ssl_ctx_st SSL_CTX;

to

typedef struct ssl_ctx_st SSL_CTX;


At an API level, any function that worked on the SSL_CTX structure that existed 
before this change was unaffected. For example, the function 
SSL_CTX_use_certificate has the same C API in both versions:

int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x);

Unfortunately, in Swift the API for this function changes dramatically, from 

func SSL_CTX_use_certificate(_ ctx: UnsafeMutablePointer!,
  _ x: 
UnsafeMutablePointer!) -> Int32

to

func SSL_CTX_use_certificate(_ ctx: OpaquePointer!,
  _ x: OpaquePointer!) 
-> Int32

The reason this is problematic is that there is no implicit cast in either 
direction between UnsafeMutablePointer and OpaquePointer. This means the API 
here has changed in an incompatible way: types that are valid before the 
structure was made opaque are not valid afterwards. This adds a pretty 
substantial burden to supporting multiple versions of the same library from 
Swift code.

So far I have thought of the following solutions to this problem that I can 
implement today:

1. Write a C wrapper library that exposes a third, consistent type that is the 
same on all versions. Most likely this would be done by re-exposing all these 
methods with arguments that take `void *` and performing the cast in C code. 
This, unfortunately, loses some of the Swift compiler’s ability to enforce type 
safety, as all these arguments will now be UnsafeRawPointer. This is not any 
worse than OpaquePointer, but it’s objectively worse than the un-opaqued 
version.

2. Write a C wrapper library that embeds these pointers in single, non-opaque 
structures with separate types. This allows us to keep the type safety at the 
cost of verbosity and an additional layer of indirection.

3. Write two different Swift wrappers for each of these versions that expose 
the same outer types, and transform them internally. Not ideal: the conditional 
compilation story here isn’t good and distributing this library via Swift PM 
would be hard.

I’d be really interested in hearing whether there is a solution I’m missing 
that can be implemented today. If there is *not* such a solution, is there 
interest in attempting to tackle this problem in Swift more directly? There are 
plenty of language changes that could be made to solve this solution (e.g. 
changing OpaquePointer to OpaquePointer but making it impossible to 
dereference, then treating UnsafePointer as a subclass of OpaquePointer, 
or making OpaquePointer a protocol implemented by UnsafePointer, or all 
kinds of other things), but I wanted to hear from the 

Re: [swift-evolution] [draft] Introduce Sequence.filteredMap(_:)

2017-10-24 Thread David Hart via swift-evolution
I also cast my vote for filterMap. It’s concise, understandable and is kind of 
a term of art also.

> On 24 Oct 2017, at 02:56, BJ Homer via swift-evolution 
>  wrote:
> 
> I agree with Xiaodi; I like ‘filterMap’ more than ‘filteredMap’. But both are 
> superior to ‘flatMap’ in this context.
> 
> -BJ
> 
> On Oct 23, 2017, at 5:22 PM, Max Moiseev  > wrote:
> 
>> It occurred to me that filteringMap(_:) should be even more descriptive, 
>> still conform to the guidelines, although similarly unprecedented and 
>> un-googlable.
>> 
>> Max
>> 
>>> On Oct 23, 2017, at 3:52 PM, Xiaodi Wu >> > wrote:
>>> 
>>> +1 in general. As to the name: since 'map' is used as a term of art, 
>>> 'filterMap' seems superior to 'filteredMap', which half follows naming 
>>> guidelines and half is a term of art; neither is immediately comprehensible 
>>> but 'filterMap' can be googled and has precedents in other languages.
>>> On Mon, Oct 23, 2017 at 17:24 BJ Homer via swift-evolution 
>>> > wrote:
>>> I strongly agree! In fact, I just started writing up a similar proposal the 
>>> other day, but hadn’t had time to finish it yet.
>>> 
>>> The current name for this particular filtering variant is not particularly 
>>> descriptive. It’s certainly not obvious to newcomers that ‘flatMap’ will 
>>> filter out results. And it’s not true to the existing usage of ‘flatMap' 
>>> from other languages; you have to really squint at it to see how any 
>>> “flattening” is happening at all.
>>> 
>>> So yes, a big +1 from me. Thanks!
>>> 
>>> -BJ Homer
>>> 
 On Oct 23, 2017, at 4:15 PM, Max Moiseev via swift-evolution 
 > wrote:
 
 Hi swift-evolution!
 
 I would like to propose the following change to the standard library:
 
 deprecate `Sequence.flatMap(_: (Element) -> U?) -> [U]` and make this 
 functionality available under a new name `Sequence.filteredMap(_:)`.
 
 The draft is available at 
 https://gist.github.com/moiseev/2f36376c8ef4c2b1273cff0bfd9c3b95 
  and is 
 included below for your convenience.
 
 Max
 
 Introduce Sequence.filteredMap(_:)
 
 Proposal: SE- 
 Authors: Max Moiseev 
 Review Manager: TBD
 Status: Awaiting implementation
  
 Introduction
 
 We propose to deprecate the controversial version of a Sequence.flatMap 
 method and provide the same functionality under a different, and 
 potentially more descriptive, name.
 
  
 Motivation
 
 The Swift standard library currently defines 3 distinct overloads for 
 flatMap:
 
 Sequence.flatMap(_: (Element) -> S) -> [S.Element]
 where S : Sequence
 Optional.flatMap(_: (Wrapped) -> U?) -> U?
 Sequence.flatMap(_: (Element) -> U?) -> [U]
 The last one, despite being useful in certain situations, can be (and 
 often is) misused. Consider the following snippet:
 
 struct Person {
   var age: Int
   var name: String
 }
 
 func getAges(people: [Person]) -> [Int] {
   return people.flatMap { $0.age }
 }
 What happens inside getNames is: thanks to the implicit promotion to 
 Optional, the result of the closure gets wrapped into a .some, then 
 immediately unwrapped by the implementation of flatMap, and appended to 
 the result array. All this unnecessary wrapping and unwrapping can be 
 easily avoided by just using map instead.
 
 func getAges(people: [Person]) -> [Int] {
   return people.map { $0.age }
 }
 It gets even worse when we consider future code modifications, like the 
 one where Swift 4 introduced a Stringconformance to the Collection 
 protocol. The following code used to compile (due to the flatMap overload 
 in question).
 
 func getNames(people: [Person]) -> [String] {
   return people.flatMap { $0.name }
 }
 But it no longer does, because now there is a better overload that does 
 not involve implicit promotion. In this particular case, the compiler 
 error would be obvious, as it would point at the same line where flatMap 
 is used. Imagine however if it was just a let names = people.flatMap { 
 $0.name  } statement, and the names variable were used 
 elsewhere. The compiler error would be misleading.
 
  
 Proposed
  solution

Re: [swift-evolution] [draft] Introduce Sequence.filteredMap(_:)

2017-10-24 Thread Nobuo Saito via swift-evolution
Hi there,

In my opinion, `map` vs `flatMap` confusing comes from implicitly casting
`T` to `T?`.
I believe it make many confusing and problems that compiler allow this
implicitly casting.
1 way of solve this topic that show warning if use implicitly casting `T`
to `T?`. Of course it should be explict casting can avoid this warning.
Such as `x as Int?`, `Int?.some(x)`, `intClosure as (() -> Int?)`.

2017-10-24 7:15 GMT+09:00 Max Moiseev via swift-evolution <
swift-evolution@swift.org>:

> Hi swift-evolution!
>
> I would like to propose the following change to the standard library:
>
> deprecate `Sequence.flatMap(_: (Element) -> U?) -> [U]` and make this
> functionality available under a new name `Sequence.filteredMap(_:)`.
>
> The draft is available at https://gist.github.com/moi
> seev/2f36376c8ef4c2b1273cff0bfd9c3b95 and is included below for your
> convenience.
>
> Max
>
> Introduce Sequence.filteredMap(_:)
>
>- Proposal: SE- 
>- Authors: Max Moiseev 
>- Review Manager: TBD
>- Status: Awaiting implementation
>
>
> 
> Introduction
>
> We propose to deprecate the controversial version of a Sequence.flatMap method
> and provide the same functionality under a different, and potentially more
> descriptive, name.
>
> 
> Motivation
>
> The Swift standard library currently defines 3 distinct overloads for
> flatMap:
>
> Sequence.flatMap(_: (Element) -> S) -> [S.Element]
> where S : SequenceOptional.flatMap(_: (Wrapped) -> U?) -> 
> U?Sequence.flatMap(_: (Element) -> U?) -> [U]
>
> The last one, despite being useful in certain situations, can be (and
> often is) misused. Consider the following snippet:
>
> struct Person {
>   var age: Int
>   var name: String
> }
> func getAges(people: [Person]) -> [Int] {
>   return people.flatMap { $0.age }
> }
>
> What happens inside getNames is: thanks to the implicit promotion to
> Optional, the result of the closure gets wrapped into a .some, then
> immediately unwrapped by the implementation of flatMap, and appended to
> the result array. All this unnecessary wrapping and unwrapping can be
> easily avoided by just using map instead.
>
> func getAges(people: [Person]) -> [Int] {
>   return people.map { $0.age }
> }
>
> It gets even worse when we consider future code modifications, like the
> one where Swift 4 introduced a Stringconformance to the Collection protocol.
> The following code used to compile (due to the flatMap overload in
> question).
>
> func getNames(people: [Person]) -> [String] {
>   return people.flatMap { $0.name }
> }
>
> But it no longer does, because now there is a better overload that does
> not involve implicit promotion. In this particular case, the compiler error
> would be obvious, as it would point at the same line where flatMap is
> used. Imagine however if it was just a let names = people.flatMap { $
> 0.name } statement, and the names variable were used elsewhere. The
> compiler error would be misleading.
>
> Proposed
> solution
>
> We propose to deprecate the controversial overload of flatMap and
> re-introduce the same functionality under a new name. The name being
> filteredMap(_:) as we believe it best describes the intent of this
> function.
>
> For reference, here are the alternative names from other languages:
>
>- Haskell, Idris  mapMaybe :: (a -> Maybe b) -> [a] -> [b]
>- Ocaml (Core and Batteries)  filter_map : 'a t -> f:('a -> 'b option)
>-> 'b t
>- F#  List.choose : ('T -> 'U option) -> 'T list -> 'U list
>- Rust  fn filter_map(self, f: F) -> FilterMap where F:
>FnMut(Self::Item) -> Option
>- Scala  def collect[B](pf: PartialFunction[A, B]): List[B]
>
>
> Source
> compatibility
>
> Since the old function will still be available (although deprecated) all
> the existing code will compile, producing a deprecation warning and a
> fix-it.
>
> Effect
> on ABI stability
>
> This is an additive API change, and does not affect ABI stability.
>
> Effect
> on API resilience
>
> Ideally, the deprecated flatMap overload would not exist at the time when
> ABI stability is declared, but in the worst case, it will be available in a
> deprecated form from a library post-ABI stability.
>
> Alternatives
> considered
>
> It was attempted in the past to warn about this kind of misuse and do the
> right thing instead by