Re: [swift-evolution] [Pitch] Guard/Catch

2017-10-07 Thread Jon Shier via swift-evolution
Oh look, a Result! Yes, this is a very useful type that should be part of the 
base language. Both guard / catch and Result would be great for Swift’s error 
handling.



Jon

> On Oct 8, 2017, at 2:01 AM, Tyler Cloutier via swift-evolution 
>  wrote:
> 
> Also the Scala approach already works quite nicely in Swift 4 in case anyone 
> was curious:
> 
> enum Try {
> case success(T)
> case failure(Error)
> 
> init(_ f: @autoclosure () throws -> T) {
> do {
> self = .success(try f())
> } catch {
> self = .failure(error)
> }
> }
> }
> 
> 
> let handlerDisposableTry = Try(try startHandler(observer))
> 
> switch handlerDisposableTry {
> case .success(let x):
> x?.dispose()
> case .failure(let error):
> print(error)
> }
> 
> It’s just a touch awkward with the double try.
> 
> Tyler
> 
> 
>>> On Oct 7, 2017, at 10:42 PM, Tyler Cloutier  wrote:
>>> 
>>> try startHandler(observer) catch {
>>> observer.sendFailed(error)
>>> }
>> 
>> 
>> Technically the above doesn’t make sense. Please disregard.
>> 
>>> On Oct 7, 2017, at 10:35 PM, Tyler Cloutier  wrote:
>>> 
>>> Has there been any progress on this? I came here to propose this but came 
>>> upon this thread first.
>>> 
>>> This proposal goes way beyond sugar. I find myself constantly in the 
>>> following situation:
>>> 
>>> let observer = Observer(with: CircuitBreaker(holding: self))
>>> do {
>>> let handlerDisposable = try startHandler(observer)
>>> } catch {
>>> observer.sendFailed(error)
>>> }
>>> 
>>> cancelDisposable = ActionDisposable {
>>> observer.sendInterrupted()
>>> handlerDisposable?.dispose() // Error handlerDisposable is 
>>> not defined here
>>> }
>>> 
>>> It’s not as simple as putting it all in the do block because then I’ll be 
>>> catching errors I might not want to catch! (In this case if the initializer 
>>> of ActionDisposable was capable of throwing.)
>>> 
>>> This is my frustration with every language that has this style of error 
>>> handling. FWIW, Scala is the only language that I have seen with this style 
>>> of error handling that solves this problem. The built-in type `Try` 
>>> combined with pattern matching fixes this issue of over extending the catch 
>>> area. Which is kinda nifty and also bridges the functional gap as well.
>>> 
>>> object Try {
>>> /** Constructs a `Try` using the by-name parameter.  This
>>> * method will ensure any non-fatal exception is caught and a
>>> * `Failure` object is returned.
>>> def apply[T](r: => T): Try[T] =
>>>   try Success(r) catch {
>>> case NonFatal(e) => Failure(e)
>>>   }
>>> }
>>> }
>>> 
>>> It also would make
>>> 
>>> try startHandler(observer) catch {
>>> observer.sendFailed(error)
>>> }
>>> 
>>> an obvious extension which to me makes sense since it’s just treating the 
>>> one function call expression as it’s own implicit do block.
>>> 
>>> Tyler
>>> 
>>> 
>>> 
 On Jul 11, 2017, at 10:31 AM, Christopher Kornher via swift-evolution 
  wrote:
 
 
 
 Begin forwarded message:
 
 From: Christopher Kornher 
 Subject: Re: [swift-evolution] [Pitch] Guard/Catch
 Date: July 10, 2017 at 5:10:15 PM MDT
 To: Elviro Rocca 
 
 This messages was modified from the original accidentally sent out 
 privately, earlier.
 
 FYI this works today in Xcode 9.0 beta 2 playgrounds:
 
 ```
 class X {
 init() throws {}
 
 func foo() {
 print( "Things succeeded" )
 }
 }
 
 func bar() throws -> X  { return try X() }
 
 
 func f()
 {
 guard let x1:X = try? X(), let x2:X = try? bar() else {
 print( "Things failed ")
 return
 }
 
 x1.foo()
 x2.foo()
 }
 
 f()// works
 ```
 
 
 Most of the examples of this proposed feature don’t handle the exceptions 
 other than to perform an early return. 
 So, without handing exceptions,  the only unhandled case is a 
 non-returning throwing function or init:
  
 ```
 class X {
 init() throws {}
 
 func foo() {
 print( "Things succeeded" )
 }
 }
 
 func bar() throws{ let _ =  try X() }
 
 
 func f()
 {
 do {
 try bar()
 } catch {
 return
 }
 
 guard let x:X = try? X() else {
 print( "Things failed ")
 return
 }
 
 x.foo()
 }
 
 f()// works
 ```
 
 Having to call a throwing, Void method before performing the rest of a 
 non-throwing function (or closure ) seems like an edge case to me. Perhaps 
 I am just biased by my experience. I have not created or used many 
 throwing initializers and certainly none i

Re: [swift-evolution] [Pitch] Guard/Catch

2017-10-07 Thread Tyler Cloutier via swift-evolution
Also the Scala approach already works quite nicely in Swift 4 in case anyone 
was curious:

enum Try {
case success(T)
case failure(Error)

init(_ f: @autoclosure () throws -> T) {
do {
self = .success(try f())
} catch {
self = .failure(error)
}
}
}


let handlerDisposableTry = Try(try startHandler(observer))

switch handlerDisposableTry {
case .success(let x):
x?.dispose()
case .failure(let error):
print(error)
}

It’s just a touch awkward with the double try.

Tyler


> On Oct 7, 2017, at 10:42 PM, Tyler Cloutier  wrote:
> 
>> try startHandler(observer) catch {
>> observer.sendFailed(error)
>> }
> 
> 
> Technically the above doesn’t make sense. Please disregard.
> 
>> On Oct 7, 2017, at 10:35 PM, Tyler Cloutier > > wrote:
>> 
>> Has there been any progress on this? I came here to propose this but came 
>> upon this thread first.
>> 
>> This proposal goes way beyond sugar. I find myself constantly in the 
>> following situation:
>> 
>> let observer = Observer(with: CircuitBreaker(holding: self))
>> do {
>> let handlerDisposable = try startHandler(observer)
>> } catch {
>> observer.sendFailed(error)
>> }
>> 
>> cancelDisposable = ActionDisposable {
>> observer.sendInterrupted()
>> handlerDisposable?.dispose() // Error handlerDisposable is 
>> not defined here
>> }
>> 
>> It’s not as simple as putting it all in the do block because then I’ll be 
>> catching errors I might not want to catch! (In this case if the initializer 
>> of ActionDisposable was capable of throwing.)
>> 
>> This is my frustration with every language that has this style of error 
>> handling. FWIW, Scala is the only language that I have seen with this style 
>> of error handling that solves this problem. The built-in type `Try` combined 
>> with pattern matching fixes this issue of over extending the catch area. 
>> Which is kinda nifty and also bridges the functional gap as well.
>> 
>> object Try {
>>  /** Constructs a `Try` using the by-name parameter.  This
>>  * method will ensure any non-fatal exception is caught and a
>> * `Failure` object is returned.
>> def apply[T](r: => T): Try[T] =
>>   try Success(r) catch {
>> case NonFatal(e) => Failure(e)
>>   }
>> }
>> }
>> 
>> It also would make
>> 
>> try startHandler(observer) catch {
>> observer.sendFailed(error)
>> }
>> 
>> an obvious extension which to me makes sense since it’s just treating the 
>> one function call expression as it’s own implicit do block.
>> 
>> Tyler
>> 
>> 
>> 
>>> On Jul 11, 2017, at 10:31 AM, Christopher Kornher via swift-evolution 
>>> mailto:swift-evolution@swift.org>> wrote:
>>> 
>>> 
>>> 
>>> Begin forwarded message:
>>> 
>>> From: Christopher Kornher mailto:ckorn...@me.com>>
>>> Subject: Re: [swift-evolution] [Pitch] Guard/Catch
>>> Date: July 10, 2017 at 5:10:15 PM MDT
>>> To: Elviro Rocca >> >
>>> 
>>> This messages was modified from the original accidentally sent out 
>>> privately, earlier.
>>> 
>>> FYI this works today in Xcode 9.0 beta 2 playgrounds:
>>> 
>>> ```
>>> class X {
>>> init() throws {}
>>> 
>>> func foo() {
>>> print( "Things succeeded" )
>>> }
>>> }
>>> 
>>> func bar() throws -> X  { return try X() }
>>> 
>>> 
>>> func f()
>>> {
>>> guard let x1:X = try? X(), let x2:X = try? bar() else {
>>> print( "Things failed ")
>>> return
>>> }
>>> 
>>> x1.foo()
>>> x2.foo()
>>> }
>>> 
>>> f()// works
>>> ```
>>> 
>>> 
>>> Most of the examples of this proposed feature don’t handle the exceptions 
>>> other than to perform an early return. 
>>> So, without handing exceptions,  the only unhandled case is a non-returning 
>>> throwing function or init:
>>>  
>>> ```
>>> class X {
>>> init() throws {}
>>> 
>>> func foo() {
>>> print( "Things succeeded" )
>>> }
>>> }
>>> 
>>> func bar() throws{ let _ =  try X() }
>>> 
>>> 
>>> func f()
>>> {
>>> do {
>>> try bar()
>>> } catch {
>>> return
>>> }
>>> 
>>> guard let x:X = try? X() else {
>>> print( "Things failed ")
>>> return
>>> }
>>> 
>>> x.foo()
>>> }
>>> 
>>> f()// works
>>> ```
>>> 
>>> Having to call a throwing, Void method before performing the rest of a 
>>> non-throwing function (or closure ) seems like an edge case to me. Perhaps 
>>> I am just biased by my experience. I have not created or used many throwing 
>>> initializers and certainly none in guard statements, and if they were in 
>>> guard statements, the need to handle exceptions differently from any other 
>>> guard failure seems ever more unlikely.
>>> 
>>> I don’t think that the small rightward drift of exception handling is 
>>> onerous. It is hardly like the “pyramid of doom” that ```guard``` was 
>>> created

Re: [swift-evolution] [Pitch] Guard/Catch

2017-10-07 Thread Tyler Cloutier via swift-evolution
> try startHandler(observer) catch {
> observer.sendFailed(error)
> }


Technically the above doesn’t make sense. Please disregard.

> On Oct 7, 2017, at 10:35 PM, Tyler Cloutier  wrote:
> 
> Has there been any progress on this? I came here to propose this but came 
> upon this thread first.
> 
> This proposal goes way beyond sugar. I find myself constantly in the 
> following situation:
> 
> let observer = Observer(with: CircuitBreaker(holding: self))
> do {
> let handlerDisposable = try startHandler(observer)
> } catch {
> observer.sendFailed(error)
> }
> 
> cancelDisposable = ActionDisposable {
> observer.sendInterrupted()
> handlerDisposable?.dispose() // Error handlerDisposable is 
> not defined here
> }
> 
> It’s not as simple as putting it all in the do block because then I’ll be 
> catching errors I might not want to catch! (In this case if the initializer 
> of ActionDisposable was capable of throwing.)
> 
> This is my frustration with every language that has this style of error 
> handling. FWIW, Scala is the only language that I have seen with this style 
> of error handling that solves this problem. The built-in type `Try` combined 
> with pattern matching fixes this issue of over extending the catch area. 
> Which is kinda nifty and also bridges the functional gap as well.
> 
> object Try {
>   /** Constructs a `Try` using the by-name parameter.  This
>   * method will ensure any non-fatal exception is caught and a
> * `Failure` object is returned.
> def apply[T](r: => T): Try[T] =
>   try Success(r) catch {
> case NonFatal(e) => Failure(e)
>   }
> }
> }
> 
> It also would make
> 
> try startHandler(observer) catch {
> observer.sendFailed(error)
> }
> 
> an obvious extension which to me makes sense since it’s just treating the one 
> function call expression as it’s own implicit do block.
> 
> Tyler
> 
> 
> 
>> On Jul 11, 2017, at 10:31 AM, Christopher Kornher via swift-evolution 
>> mailto:swift-evolution@swift.org>> wrote:
>> 
>> 
>> 
>> Begin forwarded message:
>> 
>> From: Christopher Kornher mailto:ckorn...@me.com>>
>> Subject: Re: [swift-evolution] [Pitch] Guard/Catch
>> Date: July 10, 2017 at 5:10:15 PM MDT
>> To: Elviro Rocca > >
>> 
>> This messages was modified from the original accidentally sent out 
>> privately, earlier.
>> 
>> FYI this works today in Xcode 9.0 beta 2 playgrounds:
>> 
>> ```
>> class X {
>> init() throws {}
>> 
>> func foo() {
>> print( "Things succeeded" )
>> }
>> }
>> 
>> func bar() throws -> X  { return try X() }
>> 
>> 
>> func f()
>> {
>> guard let x1:X = try? X(), let x2:X = try? bar() else {
>> print( "Things failed ")
>> return
>> }
>> 
>> x1.foo()
>> x2.foo()
>> }
>> 
>> f()// works
>> ```
>> 
>> 
>> Most of the examples of this proposed feature don’t handle the exceptions 
>> other than to perform an early return. 
>> So, without handing exceptions,  the only unhandled case is a non-returning 
>> throwing function or init:
>>  
>> ```
>> class X {
>> init() throws {}
>> 
>> func foo() {
>> print( "Things succeeded" )
>> }
>> }
>> 
>> func bar() throws{ let _ =  try X() }
>> 
>> 
>> func f()
>> {
>> do {
>> try bar()
>> } catch {
>> return
>> }
>> 
>> guard let x:X = try? X() else {
>> print( "Things failed ")
>> return
>> }
>> 
>> x.foo()
>> }
>> 
>> f()// works
>> ```
>> 
>> Having to call a throwing, Void method before performing the rest of a 
>> non-throwing function (or closure ) seems like an edge case to me. Perhaps I 
>> am just biased by my experience. I have not created or used many throwing 
>> initializers and certainly none in guard statements, and if they were in 
>> guard statements, the need to handle exceptions differently from any other 
>> guard failure seems ever more unlikely.
>> 
>> I don’t think that the small rightward drift of exception handling is 
>> onerous. It is hardly like the “pyramid of doom” that ```guard``` was 
>> created to fix.
>> 
>> ```
>> func f( y:Int? = nil )
>> {
>> do {
>> try bar()
>> let x:X = try X()
>> 
>> guard let y = y else {
>> print( "No y")
>> return
>> }
>> 
>> x.foo()
>> print( "y=\(y)")
>> } catch {
>> // Handle some exceptions.
>> return
>> }
>> }
>> ```
>> 
>> On Jul 10, 2017, at 1:45 AM, Elviro Rocca via swift-evolution 
>> mailto:swift-evolution@swift.org>> wrote:
>> 
>> This is not a sugar proposal, in the same way as "guard" is not syntactic 
>> sugar, because it requires exiting the scope on the else branch, adding 
>> expressive power and safety to the call: also, the sugary part is pretty 
>> important because it avoids nested parentheses and very clearl

Re: [swift-evolution] [Pitch] Guard/Catch

2017-10-07 Thread Tyler Cloutier via swift-evolution
Has there been any progress on this? I came here to propose this but came upon 
this thread first.

This proposal goes way beyond sugar. I find myself constantly in the following 
situation:

let observer = Observer(with: CircuitBreaker(holding: self))
do {
let handlerDisposable = try startHandler(observer)
} catch {
observer.sendFailed(error)
}

cancelDisposable = ActionDisposable {
observer.sendInterrupted()
handlerDisposable?.dispose() // Error handlerDisposable is not 
defined here
}

It’s not as simple as putting it all in the do block because then I’ll be 
catching errors I might not want to catch! (In this case if the initializer of 
ActionDisposable was capable of throwing.)

This is my frustration with every language that has this style of error 
handling. FWIW, Scala is the only language that I have seen with this style of 
error handling that solves this problem. The built-in type `Try` combined with 
pattern matching fixes this issue of over extending the catch area. Which is 
kinda nifty and also bridges the functional gap as well.

object Try {
/** Constructs a `Try` using the by-name parameter.  This
* method will ensure any non-fatal exception is caught and a
* `Failure` object is returned.
def apply[T](r: => T): Try[T] =
  try Success(r) catch {
case NonFatal(e) => Failure(e)
  }
}
}

It also would make

try startHandler(observer) catch {
observer.sendFailed(error)
}

an obvious extension which to me makes sense since it’s just treating the one 
function call expression as it’s own implicit do block.

Tyler



> On Jul 11, 2017, at 10:31 AM, Christopher Kornher via swift-evolution 
>  wrote:
> 
> 
> 
> Begin forwarded message:
> 
> From: Christopher Kornher mailto:ckorn...@me.com>>
> Subject: Re: [swift-evolution] [Pitch] Guard/Catch
> Date: July 10, 2017 at 5:10:15 PM MDT
> To: Elviro Rocca  >
> 
> This messages was modified from the original accidentally sent out privately, 
> earlier.
> 
> FYI this works today in Xcode 9.0 beta 2 playgrounds:
> 
> ```
> class X {
> init() throws {}
> 
> func foo() {
> print( "Things succeeded" )
> }
> }
> 
> func bar() throws -> X  { return try X() }
> 
> 
> func f()
> {
> guard let x1:X = try? X(), let x2:X = try? bar() else {
> print( "Things failed ")
> return
> }
> 
> x1.foo()
> x2.foo()
> }
> 
> f()// works
> ```
> 
> 
> Most of the examples of this proposed feature don’t handle the exceptions 
> other than to perform an early return. 
> So, without handing exceptions,  the only unhandled case is a non-returning 
> throwing function or init:
>  
> ```
> class X {
> init() throws {}
> 
> func foo() {
> print( "Things succeeded" )
> }
> }
> 
> func bar() throws{ let _ =  try X() }
> 
> 
> func f()
> {
> do {
> try bar()
> } catch {
> return
> }
> 
> guard let x:X = try? X() else {
> print( "Things failed ")
> return
> }
> 
> x.foo()
> }
> 
> f()// works
> ```
> 
> Having to call a throwing, Void method before performing the rest of a 
> non-throwing function (or closure ) seems like an edge case to me. Perhaps I 
> am just biased by my experience. I have not created or used many throwing 
> initializers and certainly none in guard statements, and if they were in 
> guard statements, the need to handle exceptions differently from any other 
> guard failure seems ever more unlikely.
> 
> I don’t think that the small rightward drift of exception handling is 
> onerous. It is hardly like the “pyramid of doom” that ```guard``` was created 
> to fix.
> 
> ```
> func f( y:Int? = nil )
> {
> do {
> try bar()
> let x:X = try X()
> 
> guard let y = y else {
> print( "No y")
> return
> }
> 
> x.foo()
> print( "y=\(y)")
> } catch {
> // Handle some exceptions.
> return
> }
> }
> ```
> 
> On Jul 10, 2017, at 1:45 AM, Elviro Rocca via swift-evolution 
> mailto:swift-evolution@swift.org>> wrote:
> 
> This is not a sugar proposal, in the same way as "guard" is not syntactic 
> sugar, because it requires exiting the scope on the else branch, adding 
> expressive power and safety to the call: also, the sugary part is pretty 
> important because it avoids nested parentheses and very clearly states that 
> if the guard condition is not fulfilled, the execution will not reach the 
> next lines of code. Guard is useful to push the programmer to at least 
> consider an early return instead of branching code paths, to achieve better 
> clarity, readability and lower complexity, and I suspect is one of the best 
> Swift features for many people.
> 
> Also, the case that the proposal aims to cover is not an edge case at all for 
> a lot 

Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-07 Thread Chris Lattner via swift-evolution
On Oct 5, 2017, at 1:30 PM, Joe Groff  wrote:
>> On Oct 4, 2017, at 9:24 PM, Chris Lattner  wrote:
>> On Oct 4, 2017, at 9:44 AM, Joe Groff  wrote:
 I disagree.  The semantics being proposed perfectly overlap with the 
 transitional plan for overlays (which matters for the next few years), but 
 they are the wrong default for anything other than overlays and the wrong 
 thing for long term API evolution over the next 20 years.
>>> 
>>> I disagree with this. 'inline' functions in C and C++ have to be backed by 
>>> a symbol in the binary in order to guarantee function pointer identity, but 
>>> we don't have that constraint. Without that constraint, there's almost no 
>>> way that having a fallback definition in the binary is better:
>>> 
>>> - It becomes an ABI compatibility liability that has to be preserved 
>>> forever. 
>> 
>> This seems like a marginal win at all.  Saying that you want to publish a 
>> symbol as public API but not have it be ABI is a bit odd.  What is the 
>> usecase (other than the Swift 3/4/5 transition period)?
> 
> I think it's a bigger win than you give it credit. If the function only 
> exists in client code, then the library can much more aggressively deprecate 
> and remove or replace the API, since it only has to worry about source 
> compatibility and not deployed binary compatibility. If introducing 
> `@inlinable` later further requires new clients to emit-into-client from that 
> point on, so that the in-dylib entry point only exists for backward 
> compatibility, then you get a free "linked-on-or-after" boundary where you 
> can fix quirks or shed compatibility behavior in the inlinable version while 
> preserving it in the binary.

I recognize the points you’re trying to make, but I’m not aware of sufficient 
experience with the model that makes me have any faith that it is the right 
default.  Consider:

1) Objective-C is widely known and proven for maintaining long-lived stable 
ABIs.  It worries (almost) equally about source and binary compatibility, 
because one without the other is odd.

2) C++ is widely known for both terrible source and binary compatibility, as 
well as for extensive code bloat.  It uses the model you’re describing.

Are you familiar with any system that uses the model you’re describing that 
provides good source/binary stability across api evolutions, and that does not 
inflict massive code bloat?


>>> - It increases binary size for a function that's rarely used, and which is 
>>> often much larger as an outlined generic function than the simple operation 
>>> that can be inlined into client code. Inlining makes the most sense when 
>>> the inlined operation is smaller than a function call, so in many cases the 
>>> net dylib + executable size would increase.
>> 
>> I can see this argument, but you’re basically saying that a sufficiently 
>> smart programmer can optimize code size based on (near) perfect knowledge of 
>> the symbol and all clients.  I don’t think this is realistic for a number of 
>> reasons.  In general, an API vendor has no way to know:
>> 
>> 1) how many clients it will have, potentially in multiple modules that get 
>> linked into a single app.
>> 2) on which types a generic function will be used with.
>> 3) what the code size tradeoffs ARE, e.g. if you have a large function that 
>> doesn’t use the archetype much, there is low bloat.
>> 
>> Furthermore, we have evidence from the C++ community that people are very 
>> eager to mark lots of things inlinable regardless of the cost of doing so.  
>> Swift may end up being different, but programmers still have no general way 
>> to reason about code size given their declaration and without perfect 
>> knowledge of the clients.
>> 
>> The code of the approach I’m advocating is one *single* implementation gets 
>> generated in the module that defines the decl.  This can lead the N 
>> instantiations of exactly the same unspecialized code (consider the currying 
>> and other cases) in N different modules that end up in an app.  This seems 
>> like the right tradeoff.
> 
> If we're talking about inlinable functions, then we're already talking about 
> functions generally on the small end of the scale,

What?  Programmers can and will mark tons of things inlinable.  This is well 
known from the C++ community.  I see nothing in your design that would lead to 
the conclusion that “only small functions” would get marked inlinable.

Even if we were dealing with disciplined programmers, it is a pretty 
meaningless and bad heuristic to make them decide about inlinability (in the 
sense you describe) since the profitability of inlining a function body depends 
on a ton of things.  This includes target processor architecture, but even more 
so the detailed behavior of the function body, and also the contextual 
information at specific calls sites (e.g. constant parameters).  Programmers 
will not be able to judge this sort of thing, even detailed cost models looking 
at spec

Re: [swift-evolution] Pitch: Cross-module inlining and specialization

2017-10-07 Thread Chris Lattner via swift-evolution

> On Oct 5, 2017, at 9:32 AM, Joe Groff  wrote:
> 
>>> 
>>> The suggestion to have this semantics was originally my fault, I believe, 
>>> and it arose from the observation that if we have 'inlinable' backed by a 
>>> symbol in the binary, then we'd also want the 'must be emitted by client' 
>>> attribute. I think 'must be emitted by client' is going to almost always be 
>>> preferable for an inlinable function, though, so it's better to have the 
>>> single attribute with this behavior, only constrained by backward 
>>> deployment.
>> 
>> What is the use case of “must be emitted by client” attribute?  If I imagine 
>> that the Swift 5 standard library is shipped in the OS, I can see cases 
>> where deprecated/legacy shims for Swift3/4 compatibility would be emitted 
>> into the client but not shipped in the OS.  Those seem relatively obscure 
>> though.
> 
> You could just as easily pose the opposite question—what's the use case for a 
> symbol in the dylib when the definition is visible to clients? Evaluating the 
> tradeoffs, we feel like it's better not to unless backward compatibility 
> demands it.

The behavior I’m proposing dovetails with the overall design of swift 
resilience progressive disclosure:

1) You can be fast and loose with a symbol, so long as you don’t define it as 
public.
2) Making it public allows you to be fast and loose within your module, but you 
have to opt into guarantees for other modules.
3) You can ship your symbol as public, then grant additional guarantees 
(overridability/subclassability or inlinability) in a subsequent release after 
you gain experience with it.

I think it is hugely problematic that transitioning from “public” to “inlinable 
public” would be an ABI break with your approach.

I would much rather see a model where “public” can graduate to “inlinable 
public” in an ABI compatible way, but that there were a “alwaysinlined public” 
concept (with a sufficiently scary name) for power users that want the 
semantics that you’re arguing for.

-Chris


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


Re: [swift-evolution] Pitch: Restrict Cross-module Struct Initializers

2017-10-07 Thread Chris Lattner via swift-evolution

> On Oct 6, 2017, at 2:32 PM, Jordan Rose via swift-evolution 
>  wrote:
> 
> While working on the non-exhaustive enums proposal I had it pointed out to me 
> that structs actually currently leak implementation details across module 
> boundaries, specifically their full set of stored properties. This only comes 
> up in one place: when making an initializer for the struct in an extension in 
> another module. We really want people to be able to change the stored 
> properties in their structs between releases without it being a source 
> break—that's half the point of computed properties—and it's also important 
> for a struct author to be able to enforce invariants across the struct's 
> properties. So after talking to a few other Apple Swift folks I put together 
> this proposal:
> 
> https://github.com/jrose-apple/swift-evolution/blob/restrict-cross-module-struct-initializers/proposals/-restrict-cross-module-struct-initializers.md
>  
> 
> 
> This one's way smaller than the enum one, and hopefully fairly 
> uncontroversial. Feedback welcome!

Great catch, +1 to the proposal!

Please add the point Xiodi mentions to the writing though so that the review 
cycle adequately discusses it.  A "fragile struct” (for some definition of 
fragility), but definitely including C structs, will have knowable stored 
properties, and it isn’t clear that these should be subjected to this 
restriction.  The win of the restriction in that case is the invariant point 
you’re making.  It is best to address this head-on in the writing, and mention 
the alternate approach in the ‘alternatives considered’ section (along with why 
you think you’ve picked the right choice).

-Chris


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


Re: [swift-evolution] Fix "private extension" (was "Public Access Modifier Respected in Type Definition")

2017-10-07 Thread Jose Cheyo Jimenez via swift-evolution


> On Oct 7, 2017, at 10:17 AM, Nevin Brackett-Rozinsky via swift-evolution 
>  wrote:
> 
> Two weeks ago I had a fairly strong opinion about “private extension” 
> behavior. After following this discussion, I now have no opinion on the 
> matter.
> 
> I would summarize the points on both sides as follows:
> 
> For the change:
> • It is surprising to many people that members of a private extension are 
> implicitly fileprivate.
> • There is currently no way to make an extension whose members default to 
> private.
> 
> Against the change:
> • The proposal is source-breaking.
> • The proposal makes “fileprivate” more common.
> • A private extension and a (top-level) private type both currently have 
> implicitly fileprivate members. The proposal breaks that symmetry.
> 
Great summary! Thank you. 
> Notable questions:
> • Currently “open” cannot be applied to an extension at all, should we allow 
> it?
> • Might we ever want to allow nested (non-top level) extensions, and if so 
> how should access levels on them work?

This could be a solution that would not be source breaking to the topic at 
hand. 

extension MyType {
private extension {
// “true” private here
}
}

I think it would be a good idea to limit the nesting with other extensions. 
Other idea. 

extension { // bag of extensions
private extension MyType {
// “true” private here
}
fileprivate extension MyType2 {
// fileprivate  here
}
}

I rather have a comprehensive sub module system than nested extensions though.  
:)

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


Re: [swift-evolution] Fix "private extension" (was "Public Access Modifier Respected in Type Definition")

2017-10-07 Thread Xiaodi Wu via swift-evolution
On Sat, Oct 7, 2017 at 12:21 Jose Cheyo Jimenez  wrote:

>
>
> On Oct 7, 2017, at 8:28 AM, Xiaodi Wu  wrote:
>
> This, I think, is the most persuasive argument available here; it provides
> a concrete use case to justify why one design is superior to the other.
>
>
> open extension do not exist either. :)
>

That could be fixed too then.

On Sat, Oct 7, 2017 at 10:26 David Hart via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> One argument: without this fix, private is the only access level for which
>> we have no means to easily and implicitly apply an access level to a group
>> of members. And it bums me to have to explicitly type private on ever
>> single member to achieve the same result as I can with any other access
>> level.
>>
>
> In the same way that we need to be explicit about open in extension
> members or public in public type members; the lowest access version of
> scope private needs to also be explicit in private extension members and
> top level private concrete type members.
>
> The premise of 169 was never about creating a new version of scope private
> that could only be used in extensions. It just relaxed the rules for
> explicit private extension members.
>
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Property Getter Return Statement

2017-10-07 Thread Tony Allevato via swift-evolution
I think the important thing to consider is, what advantage would such a
feature provide *other* than to reduce keystrokes? (I don't personally
think that optimizing for keys pressed by itself should be a goal.)

In the case of closures, single expression closures without "return"
improve readability because such closures are often chained for functional
programming patterns:

someArray.filter { $0.isFloopy }.map { $0.grobber }

Having "return" there would be noise that detracts from understanding
what's going on in that algorithm. It's also worth noting that in this
context, the closure *itself* is also an expression.

In functions, property getters, and subscripts, the same constraints don't
really hold. They're declarations, not expressions, so they don't chain
together and they're not subject to the same readability problems as
closure expressions.


On Sat, Oct 7, 2017 at 9:59 AM Nevin Brackett-Rozinsky via swift-evolution <
swift-evolution@swift.org> wrote:

> On Sat, Oct 7, 2017 at 11:24 AM, Xiaodi Wu  wrote:
>
>> This has been brought up on the list before. For instance:
>>
>> https://github.com/apple/swift-evolution/pull/608
>>
>> Chris Lattner’s response at that time was:
>>
>> ‘Just MHO, but I consider this syntactic sugar, not a fundamental feature
>> that fits the goal of Swift 4 stage 2.
>>
>> ‘I’m also pretty opposed to doing it at any time. The rationale of
>> “implicit return” in closures is specifically because they are limited to a
>> single expression, which makes the semantics “obvious”. This was carefully
>> considered.’
>
>
> This objection is not applicable, because we are discussing the
> possibility to omit “return” exactly when there is a single expression in
> the getter.
>
> Nevin
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Fix "private extension" (was "Public Access Modifier Respected in Type Definition")

2017-10-07 Thread Jose Cheyo Jimenez via swift-evolution


> On Oct 7, 2017, at 8:28 AM, Xiaodi Wu  wrote:
> 
> This, I think, is the most persuasive argument available here; it provides a 
> concrete use case to justify why one design is superior to the other.

open extension do not exist either. :)

>> On Sat, Oct 7, 2017 at 10:26 David Hart via swift-evolution 
>>  wrote:
>> One argument: without this fix, private is the only access level for which 
>> we have no means to easily and implicitly apply an access level to a group 
>> of members. And it bums me to have to explicitly type private on ever single 
>> member to achieve the same result as I can with any other access level.

In the same way that we need to be explicit about open in extension members or 
public in public type members; the lowest access version of scope private needs 
to also be explicit in private extension members and top level private concrete 
type members. 

The premise of 169 was never about creating a new version of scope private that 
could only be used in extensions. It just relaxed the rules for explicit 
private extension members. 

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


Re: [swift-evolution] Fix "private extension" (was "Public Access Modifier Respected in Type Definition")

2017-10-07 Thread Nevin Brackett-Rozinsky via swift-evolution
Two weeks ago I had a fairly strong opinion about “private extension”
behavior. After following this discussion, I now have no opinion on the
matter.

I would summarize the points on both sides as follows:

For the change:
• It is surprising to many people that members of a private extension are
implicitly fileprivate.
• There is currently no way to make an extension whose members default to
private.

Against the change:
• The proposal is source-breaking.
• The proposal makes “fileprivate” more common.
• A private extension and a (top-level) private type both currently have
implicitly fileprivate members. The proposal breaks that symmetry.

Notable questions:
• Currently “open” cannot be applied to an extension at all, should we
allow it?
• Might we ever want to allow nested (non-top level) extensions, and if so
how should access levels on them work?

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


Re: [swift-evolution] Property Getter Return Statement

2017-10-07 Thread Nevin Brackett-Rozinsky via swift-evolution
On Sat, Oct 7, 2017 at 11:24 AM, Xiaodi Wu  wrote:

> This has been brought up on the list before. For instance:
>
> https://github.com/apple/swift-evolution/pull/608
>
> Chris Lattner’s response at that time was:
>
> ‘Just MHO, but I consider this syntactic sugar, not a fundamental feature
> that fits the goal of Swift 4 stage 2.
>
> ‘I’m also pretty opposed to doing it at any time. The rationale of
> “implicit return” in closures is specifically because they are limited to a
> single expression, which makes the semantics “obvious”. This was carefully
> considered.’


This objection is not applicable, because we are discussing the possibility
to omit “return” exactly when there is a single expression in the getter.

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


Re: [swift-evolution] Property Getter Return Statement

2017-10-07 Thread Tony Allevato via swift-evolution
For what it's worth, you can drop the "get" part for read-only computed
properties and write:

var session: AVCaptureSession { return layer.session }


On Sat, Oct 7, 2017 at 7:07 AM James Valaitis via swift-evolution <
swift-evolution@swift.org> wrote:

> Is it widely agreed that it is necessary to require a return statement on
> a one line property getter?
>
> var session: AVCaptureSession { get { return layer.session } }
>
> Or could we follow the convention for any other close and get rid of it?
> For me it seems redundant; the word `get` literally precedes the closure.
> ___
> 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] Fix "private extension" (was "Public Access Modifier Respected in Type Definition")

2017-10-07 Thread Xiaodi Wu via swift-evolution
This, I think, is the most persuasive argument available here; it provides
a concrete use case to justify why one design is superior to the other.
On Sat, Oct 7, 2017 at 10:26 David Hart via swift-evolution <
swift-evolution@swift.org> wrote:

> One argument: without this fix, private is the only access level for which
> we have no means to easily and implicitly apply an access level to a group
> of members. And it bums me to have to explicitly type private on ever
> single member to achieve the same result as I can with any other access
> level.
>
> On 7 Oct 2017, at 07:07, Jose Cheyo Jimenez via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>
> On Oct 6, 2017, at 9:35 PM, Tony Allevato  wrote:
>
>
>
> On Fri, Oct 6, 2017 at 9:29 PM Jose Cheyo Jimenez 
> wrote:
>
>> On Oct 6, 2017, at 8:58 PM, Tony Allevato 
>> wrote:
>>
>>
>>
>> On Fri, Oct 6, 2017 at 8:45 PM Jose Cheyo Jimenez 
>> wrote:
>>
>>> On Oct 6, 2017, at 8:01 PM, Tony Allevato 
>>> wrote:
>>>

 At the time SE-0025 was accepted, "private extension" would have been
>>> meaningless if it did not mean "fileprivate" because it predated the
>>> SE-0169 behavior extending "private" to extensions in the same file. The
>>> very issue being debated here is whether the oversight that SE-0169 did not
>>> consider extensions—now that "private extension" *could* have a meaningful
>>> use separate from "fileprivate extension"—is something that is worth
>>> correcting.
>>>
>>> If the documentation is out-of-date and needs to be updated to list
>>> describe unintuitive special behavior, why not use the opportunity to make
>>> the behavior intuitive and consistent instead?
>>>
>>>
>>> Lets say you “fix” the private extension override. Now
>>> MyClass2.myFunc2() is not accessible from outside the type.
>>> Wouldn't MyClass2.myFunc2() now be inconsistent with MyClass.myFunc()?
>>> I don’t think you can make a change to one with out causing other
>>> inconsistencies. I rest my case.  :)
>>>
>>
>> No, because a class is a concrete "thing" whose access level which—while
>> providing an upper bound for access levels of its defaulting members—is
>> otherwise independent of the access level of its members.
>>
>> Extensions, on the other hand, aren't a concrete thing of their own. The
>> access level on an extension exists *solely* as a shortcut to specify the
>> upper bound for its defaulting members that are injected into the main type.
>>
>> What happens in your example if you replace "private" with "public"? Then
>> myFunc has internal access but myFunc2 is public. So the "inconsistency"
>> you're pointing out between access inherited from a type and access
>> inherited from an extension already exists—they're apples and oranges.
>>
>> That's why access levels of classes/structs/other types aren't relevant
>> examples here—extensions treat access levels fundamentally differently.
>>
>> Sure. Extensions apply a default upper bound and types can lower the
>> upper bound of the default internal members. The upper bound on the below
>> example is the same for both when dealing with top level private.
>>
>> Extensions should resolve their upper bound accessibility where the
>> ‘private’ appears explicitly and this now happens to be the same for both
>> types and extensions regardless of how they are enforced.
>>
>
> But *why* do you think that should be? You're stating what the current
> situation is and you say that it "should" be that way, but why should we
> accept that status quo instead of making "private extension" more useful
> for people who use "private" in the sense introduced by SE-0169, when the
> argument for consistency can honestly be argued either way (the two options
> I wrote a few messages up)?
>
>
> Oh :) Because I believe that lowering the scope of “private extension”
> would undermine the spirit of 169.  169 was a compromise after 159 was
> rejected. 169 was meant to make fileprivate less common and thus more
> meaningful when it occurs in source. Where 169 was meant to relax the
> rules, the proposed “fix” would force people who now use “private
> extension” to use “fileprivate extension” thus making fileprivate more
> common. In other words, 169 was about relaxing rules and not about
> tightening down the rules or allowing “true” private to be applied as a
> default ACL extension.
>
> “scoped" `private extension` can’t be archived now in the same way that
> ‘open extension’ is not allowed. The lowest and highest ACL are not able to
> be applied as default  extension modifiers and this makes sense to me.
>
> There is no solution that will make everyone happy: maintaining the status 
> quo makes “fileprivate” too common and therefore not meaningful when it 
> occurs in source; removing or diluting scope-level access control (as in 
> SE-0159 
> 
>  and this proposal)
>
>
> https://lists.swift.org/pipermail/swift-evolution-announce/2017-

Re: [swift-evolution] Fix "private extension" (was "Public Access Modifier Respected in Type Definition")

2017-10-07 Thread David Hart via swift-evolution
One argument: without this fix, private is the only access level for which we 
have no means to easily and implicitly apply an access level to a group of 
members. And it bums me to have to explicitly type private on ever single 
member to achieve the same result as I can with any other access level.

> On 7 Oct 2017, at 07:07, Jose Cheyo Jimenez via swift-evolution 
>  wrote:
> 
> 
>> On Oct 6, 2017, at 9:35 PM, Tony Allevato  wrote:
>> 
>> 
>> 
>> On Fri, Oct 6, 2017 at 9:29 PM Jose Cheyo Jimenez  
>> wrote:
 On Oct 6, 2017, at 8:58 PM, Tony Allevato  wrote:
 
 
 
 On Fri, Oct 6, 2017 at 8:45 PM Jose Cheyo Jimenez  
 wrote:
>>> On Oct 6, 2017, at 8:01 PM, Tony Allevato  
>>> wrote:
>> At the time SE-0025 was accepted, "private extension" would have been 
>> meaningless if it did not mean "fileprivate" because it predated the 
>> SE-0169 behavior extending "private" to extensions in the same file. The 
>> very issue being debated here is whether the oversight that SE-0169 did 
>> not consider extensions—now that "private extension" *could* have a 
>> meaningful use separate from "fileprivate extension"—is something that 
>> is worth correcting.
>> 
>> If the documentation is out-of-date and needs to be updated to list 
>> describe unintuitive special behavior, why not use the opportunity to 
>> make the behavior intuitive and consistent instead?
> 
> Lets say you “fix” the private extension override. Now MyClass2.myFunc2() 
> is not accessible from outside the type. 
> Wouldn't MyClass2.myFunc2() now be inconsistent with MyClass.myFunc()? 
> I don’t think you can make a change to one with out causing other 
> inconsistencies. I rest my case.  :) 
 
 No, because a class is a concrete "thing" whose access level which—while 
 providing an upper bound for access levels of its defaulting members—is 
 otherwise independent of the access level of its members.
 
 Extensions, on the other hand, aren't a concrete thing of their own. The 
 access level on an extension exists *solely* as a shortcut to specify the 
 upper bound for its defaulting members that are injected into the main 
 type.
 
 What happens in your example if you replace "private" with "public"? Then 
 myFunc has internal access but myFunc2 is public. So the "inconsistency" 
 you're pointing out between access inherited from a type and access 
 inherited from an extension already exists—they're apples and oranges.
 
 That's why access levels of classes/structs/other types aren't relevant 
 examples here—extensions treat access levels fundamentally differently.
>>> 
>>> Sure. Extensions apply a default upper bound and types can lower the upper 
>>> bound of the default internal members. The upper bound on the below example 
>>> is the same for both when dealing with top level private.
>>> 
>>> Extensions should resolve their upper bound accessibility where the 
>>> ‘private’ appears explicitly and this now happens to be the same for both 
>>> types and extensions regardless of how they are enforced. 
>> 
>> But *why* do you think that should be? You're stating what the current 
>> situation is and you say that it "should" be that way, but why should we 
>> accept that status quo instead of making "private extension" more useful for 
>> people who use "private" in the sense introduced by SE-0169, when the 
>> argument for consistency can honestly be argued either way (the two options 
>> I wrote a few messages up)?
> 
> Oh :) Because I believe that lowering the scope of “private extension” would 
> undermine the spirit of 169.  169 was a compromise after 159 was rejected. 
> 169 was meant to make fileprivate less common and thus more meaningful when 
> it occurs in source. Where 169 was meant to relax the rules, the proposed 
> “fix” would force people who now use “private extension” to use “fileprivate 
> extension” thus making fileprivate more common. In other words, 169 was about 
> relaxing rules and not about tightening down the rules or allowing “true” 
> private to be applied as a default ACL extension.
> 
> “scoped" `private extension` can’t be archived now in the same way that ‘open 
> extension’ is not allowed. The lowest and highest ACL are not able to be 
> applied as default  extension modifiers and this makes sense to me. 
> 
> There is no solution that will make everyone happy: maintaining the status 
> quo makes “fileprivate” too common and therefore not meaningful when it 
> occurs in source; removing or diluting scope-level access control (as in 
> SE-0159 
> 
>  and this proposal)
> https://lists.swift.org/pipermail/swift-evolution-announce/2017-April/000357.html
> 
> 
> 
>> 
>>  
> 
> private class MyClass {
> static func myFunc(){ // This would now act d

Re: [swift-evolution] Property Getter Return Statement

2017-10-07 Thread Xiaodi Wu via swift-evolution
This has been brought up on the list before. For instance:

https://github.com/apple/swift-evolution/pull/608

Chris Lattner’s response at that time was:

‘Just MHO, but I consider this syntactic sugar, not a fundamental feature
that fits the goal of Swift 4 stage 2.

‘I’m also pretty opposed to doing it at any time. The rationale of
“implicit return” in closures is specifically because they are limited to a
single expression, which makes the semantics “obvious”. This was carefully
considered.’


On Sat, Oct 7, 2017 at 09:18 Nevin Brackett-Rozinsky via swift-evolution <
swift-evolution@swift.org> wrote:

> +1
>
> We don’t need “return” in single-line closures where the type is known,
> and I don’t see why it is required in single-line getters.
>
> Nevin
>
>
> On Sat, Oct 7, 2017 at 10:07 AM, James Valaitis via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>> Is it widely agreed that it is necessary to require a return statement on
>> a one line property getter?
>>
>> var session: AVCaptureSession { get { return layer.session } }
>>
>> Or could we follow the convention for any other close and get rid of it?
>> For me it seems redundant; the word `get` literally precedes the closure.
>> ___
>> 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] Property Getter Return Statement

2017-10-07 Thread Nevin Brackett-Rozinsky via swift-evolution
+1

We don’t need “return” in single-line closures where the type is known, and
I don’t see why it is required in single-line getters.

Nevin


On Sat, Oct 7, 2017 at 10:07 AM, James Valaitis via swift-evolution <
swift-evolution@swift.org> wrote:

> Is it widely agreed that it is necessary to require a return statement on
> a one line property getter?
>
> var session: AVCaptureSession { get { return layer.session } }
>
> Or could we follow the convention for any other close and get rid of it?
> For me it seems redundant; the word `get` literally precedes the closure.
> ___
> 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] Property Getter Return Statement

2017-10-07 Thread James Valaitis via swift-evolution
Is it widely agreed that it is necessary to require a return statement on a one 
line property getter?

var session: AVCaptureSession { get { return layer.session } }

Or could we follow the convention for any other close and get rid of it? For me 
it seems redundant; the word `get` literally precedes the closure.
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution