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

2017-10-08 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 
> <swift-evolution@swift.org> 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 <cloutierty...@aol.com> 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 <cloutierty...@aol.com> 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 
>>>> <swift-evolution@swift.org> wrote:
>>>> 
>>>> 
>>>> 
>>>> Begin forwarded message:
>>>> 
>>>> From: Christopher Kornher <ckorn...@me.com>
>>>> Subject: Re: [swift-evolution] [Pitch] Guard/Catch
>>>> Date: July 10, 2017 at 5:10:15 PM MDT
>>>> To: Elviro Rocca <retired.hunter.dj...@gmail.com>
>>>> 
>>>> 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()
>>>> {
>>>

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

2017-10-08 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 <cloutierty...@aol.com> 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 <cloutierty...@aol.com 
>> <mailto:cloutierty...@aol.com>> 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 
>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>>> 
>>> 
>>> 
>>> Begin forwarded message:
>>> 
>>> From: Christopher Kornher <ckorn...@me.com <mailto:ckorn...@me.com>>
>>> Subject: Re: [swift-evolution] [Pitch] Guard/Catch
>>> Date: July 10, 2017 at 5:10:15 PM MDT
>>> To: Elviro Rocca <retired.hunter.dj...@gmail.com 
>>> <mailto:retired.hunter.dj...@gmail.com>>
>>> 
>>> 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

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 <cloutierty...@aol.com> 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 
>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>> 
>> 
>> 
>> Begin forwarded message:
>> 
>> From: Christopher Kornher <ckorn...@me.com <mailto:ckorn...@me.com>>
>> Subject: Re: [swift-evolution] [Pitch] Guard/Catch
>> Date: July 10, 2017 at 5:10:15 PM MDT
>> To: Elviro Rocca <retired.hunter.dj...@gmail.com 
>> <mailto:retired.hunter.dj...@gmail.com>>
>> 
>> 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 rig

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 
> <swift-evolution@swift.org> wrote:
> 
> 
> 
> Begin forwarded message:
> 
> From: Christopher Kornher <ckorn...@me.com <mailto:ckorn...@me.com>>
> Subject: Re: [swift-evolution] [Pitch] Guard/Catch
> Date: July 10, 2017 at 5:10:15 PM MDT
> To: Elviro Rocca <retired.hunter.dj...@gmail.com 
> <mailto:retired.hunter.dj...@gmail.com>>
> 
> 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 
> <swift-evolution@swift.org <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 
> 

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

2017-07-11 Thread Elviro Rocca via swift-evolution
Not sure what you mean here. A guard/catch would allow me to handle the error 
in the catch, something that (of course) cannot be done with "try?", so 
guard/else with "try?" is not a solution. And of course returning in the catch 
side of a do/catch is like returning in the else side of a if/else, but that's 
what "guard" is about, so I probably didn't understand what's your point here.


Elviro


> Il giorno 11 lug 2017, alle ore 01:10, Christopher Kornher  
> ha scritto:
> 
> 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
> ```
> 
> So 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 
> function seems like an edge case to me 
> 
> 
>> On Jul 10, 2017, at 1:45 AM, Elviro Rocca via swift-evolution 
>> > 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 of people, including me. Rethrowing an error is something that I 
>> almost never do, and I consider the "umbrella" do/catch at the top of the 
>> call stack an anti-pattern, but I understand that many people like it and 
>> I'm not arguing against it. I am arguing in favor of having options and not 
>> pushing a particular style onto programmers, and for my (and many people's) 
>> style, a guard/catch with forced return is an excellent idea. In fact you 
>> seem to agree on the necessity of some kind of forced-returnish catch but 
>> your elaborations don't seem (to me) much better than the proposal itself.
>> 
>> Dave DeLong raised the point of weird behavior in the case of a function 
>> like:
>> 
>> 
>> func doSomething() throws → Result? { … }
>> 
>> 
>> In this case, what would the type of x be?
>> 
>> 
>> guard let x = try doSomething() catch { /// handle and return }
>> 
>> 
>> Simple, it would be Optional. I don't find this confusing at all, 
>> and if the idea that just by seeing "guard let" we should expect a 
>> non-Optional is somehow diffused, I think it's better to eradicate it.
>> 
>> First of all, if I'm returning an optional from a throwing function, it's 
>> probably the case that I want the Optional to be there in the returned 
>> value: the only reason why I would consider doing that is if the semantics 
>> of Optional are pretty meaningful in that case. For example, when parsing a 
>> JSON in which I expect a String or null to be at a certain key:
>> 
>> 
>> extension String: Error {}
>> 
>> func parseString(in dict: [String:Any], at key: String) throws -> String? {
>>  guard let x = dict[key] else { throw "No value found at '\(key)' in 
>> \(dict)" }
>>  if let x = x as? String { return x }
>>  if let x = x as? NSNull { return nil }
>>  throw "Value at '\(key)' in \(dict) is not 'string' or 'null"
>> }
>> 
>> 
>> Thus, if I'm returning an Optional from a throwing function it means that I 
>> want to clearly distinguish the two cases, so they shouldn't be collapsed in 
>> a single call:
>> 
>> 
>> guard let x = try doSomething() catch { /// handle and return }
>> guard let x = x else { /// handle and return }
>> 
>> 
>> Also, if a function returns something like "Int??", a guard-let (or if-let) 
>> on the returned value of that function will still bind an "Int?", thus 
>> unwrapping only "one level" of optional. If-let and guard-let, as of today, 
>> just unwrap a single optional level, an do not guaranteed at all that the 
>> bound value is not optional.
>> 
>> To me guard-let 

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

2017-07-10 Thread Greg Parker via swift-evolution

> On Jul 10, 2017, at 1:51 AM, David Hart via swift-evolution 
>  wrote:
> 
> I know we can’t do much about it now, but if optional binding had used the 
> same syntax as it does in pattern matching, we wouldn’t be having this 
> discussion:
> 
> guard let x = try doSomething() catch {
> // handle error
> }
> 
> guard let x? = doSomething() else {
> // handle when nil
> }

We tried pattern-matching syntax in `if let` a while ago. It was unbelievably 
unpopular. We changed it back.


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


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


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

2017-07-10 Thread Elviro Rocca via swift-evolution
I don't think that "guard let x? = ..." would be syntactically correct, AFAIK 
for matching the pattern "let x? =", as for any other pattern, you need to use 
"case", in fact the following is perfectly valid:

guard case let x? = doSomething() else {
// handle when nil
}

I think that "guard let x =" is in fact sugar for "guard case let x? =", so 
your example should really be:

guard case let x? = try doSomething() catch {
// handle error
} else {
// handle when nil
}

This would basically mean "add an extra catch when pattern-matching with a 
throwing function", same as:

switch try doSomething() {
case let x?:
// handle
case nil:
// handle   
} catch {
// handle
}

Honestly I'm still not sold in conflating the two things. I don't think it 
would be problematic to clearly separate cases when I'm binding the result of a 
throwing function (which in fact is isomorphic to a Either) and 
binding an Optional.


Elviro

> Il giorno 10 lug 2017, alle ore 10:44, David Hart  ha 
> scritto:
> 
>> 
>> On 10 Jul 2017, at 09:45, Elviro Rocca via swift-evolution 
>> > 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 of people, including me. Rethrowing an error is something that I 
>> almost never do, and I consider the "umbrella" do/catch at the top of the 
>> call stack an anti-pattern, but I understand that many people like it and 
>> I'm not arguing against it. I am arguing in favor of having options and not 
>> pushing a particular style onto programmers, and for my (and many people's) 
>> style, a guard/catch with forced return is an excellent idea. In fact you 
>> seem to agree on the necessity of some kind of forced-returnish catch but 
>> your elaborations don't seem (to me) much better than the proposal itself.
>> 
>> Dave DeLong raised the point of weird behavior in the case of a function 
>> like:
>> 
>> 
>> func doSomething() throws → Result? { … }
>> 
>> 
>> In this case, what would the type of x be?
>> 
>> 
>> guard let x = try doSomething() catch { /// handle and return }
> 
> I know we can’t do much about it now, but if optional binding had used the 
> same syntax as it does in pattern matching, we wouldn’t be having this 
> discussion:
> 
> guard let x = try doSomething() catch {
> // handle error
> }
> 
> guard let x? = doSomething() else {
> // handle when nil
> }
> 
> And mixing both would be a bit cleaner because the ? would make it explicit 
> we are doing optional binding:
> 
> guard let x? = try doSomething() catch {
> // handle error
> } else {
> // handle when nil
> }
> 
>> Simple, it would be Optional. I don't find this confusing at all, 
>> and if the idea that just by seeing "guard let" we should expect a 
>> non-Optional is somehow diffused, I think it's better to eradicate it.
>> 
>> First of all, if I'm returning an optional from a throwing function, it's 
>> probably the case that I want the Optional to be there in the returned 
>> value: the only reason why I would consider doing that is if the semantics 
>> of Optional are pretty meaningful in that case. For example, when parsing a 
>> JSON in which I expect a String or null to be at a certain key:
>> 
>> 
>> extension String: Error {}
>> 
>> func parseString(in dict: [String:Any], at key: String) throws -> String? {
>>  guard let x = dict[key] else { throw "No value found at '\(key)' in 
>> \(dict)" }
>>  if let x = x as? String { return x }
>>  if let x = x as? NSNull { return nil }
>>  throw "Value at '\(key)' in \(dict) is not 'string' or 'null"
>> }
>> 
>> 
>> Thus, if I'm returning an Optional from a throwing function it means that I 
>> want to clearly distinguish the two cases, so they shouldn't be collapsed in 
>> a single call:
>> 
>> 
>> guard let x = try doSomething() catch { /// handle and return }
>> guard let x = x else { /// handle and return }
>> 
>> 
>> Also, if a function returns something like "Int??", a guard-let (or if-let) 
>> on the returned value of that function will still bind an "Int?", thus 
>> unwrapping only "one level" of optional. If-let and guard-let, as of today, 
>> just unwrap a single optional level, an do not guaranteed at all 

[swift-evolution] [Pitch] Guard/Catch

2017-07-10 Thread Richard Adem via swift-evolution
One of the reasons I like this proposal is at a higher level we are
checking for errors and have the ability to exit early if there is an
error, I think this aligns well with what `guard` represents, at least to
me. Using `try?` effectively ignores the error so if we want convenience we
have to give up accuracy of the error handling.

It also encourages error handling, if we have a function that uses the
result of a throwing function it's very easy to do a `guard` on `try?` and
return a generic error instead of putting the function in a do/catch block.
With this proposal we can easily put the specific error handing in the
catch block.

The proposal does also changes the concept of guard somewhat, where now it
is tied directly to conditionals and `guard/else` is the core concept. The
proposal takes out `guard` as the core of and early exit statement the
result of it failing it up to how we define our handing of it.

> The obvious problem is that `guard let` in Swift is closely associated
with
> optional unwrapping. The reader is right to expect a non-optional `result`
> with `guard let` regardless of the word that comes after conditional
> expression.

Yes this does change that idea, but `guard let` is always accompanied by
else, additionally because we also use guard along with other conditionals
`guard x > 0 else {}` there isn't a strong tie of guard to optionals. The
interfered result type is set by the entire line much like `let a = x > 0 ?
"higher" : "lower"`

> The nesting and ceremony, to me, were part of Swift’s philosophy of
making error handling explicit.  Merging catch blocks into guards saves you
maybe 3-10 lines if you intended to actually handle the error(s), otherwise
this effectively try?’s  into a failable pattern match.  At which point,
you have to wonder if the error-throwing function you wrote wouldn’t be
better off just returning an Optional if you’re going to discard the
semantic content of the error.

I think this proposal goes beyond convenience as we are stating that we
want the returned value to be at the same scope as code that uses it.

If we want to save lines we can do that anyway with something like:
```
func divide(x: Int, y: Int) throws -> Int {...}
let z: Int; do { z = try divide(x: 10, y: 5) } catch {
print(error)
return
}
```

But we always want `z` to be the result of `divide(x:y:)` having it outside
the do/catch looks like we may intend it to be set by something else. With
this proposal we are tying `z` to the result of `divide(x:y:)`.

Another way could be to use a closure

```
let z:Int? = {
do {
return try divide(x: x, y: y)
} catch {
print(error)
return nil
}
}()
```
but then we have to use an optional in the case where `divide(x:y:)` does
not return one and adding another check for the optional later.

I think separating guard/else and guard/catch is a great idea because we
wouldn't have the issue of remembering what order else and catch should be
in. We can think about guard as guard/[handler]

The prior thread and in this thread there as been talk of a version without
the `guard`. This feels more like an extension of the try keyword, which
doesn't sound to bad to me. It handles the case of keeping the result in
the current scope, but it just doesn't group code in a exit early style.
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2017-07-10 Thread David Hart via swift-evolution

> On 10 Jul 2017, at 09:45, Elviro Rocca via swift-evolution 
>  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 of people, including me. Rethrowing an error is something that I almost 
> never do, and I consider the "umbrella" do/catch at the top of the call stack 
> an anti-pattern, but I understand that many people like it and I'm not 
> arguing against it. I am arguing in favor of having options and not pushing a 
> particular style onto programmers, and for my (and many people's) style, a 
> guard/catch with forced return is an excellent idea. In fact you seem to 
> agree on the necessity of some kind of forced-returnish catch but your 
> elaborations don't seem (to me) much better than the proposal itself.
> 
> Dave DeLong raised the point of weird behavior in the case of a function like:
> 
> 
> func doSomething() throws → Result? { … }
> 
> 
> In this case, what would the type of x be?
> 
> 
> guard let x = try doSomething() catch { /// handle and return }

I know we can’t do much about it now, but if optional binding had used the same 
syntax as it does in pattern matching, we wouldn’t be having this discussion:

guard let x = try doSomething() catch {
// handle error
}

guard let x? = doSomething() else {
// handle when nil
}

And mixing both would be a bit cleaner because the ? would make it explicit we 
are doing optional binding:

guard let x? = try doSomething() catch {
// handle error
} else {
// handle when nil
}

> Simple, it would be Optional. I don't find this confusing at all, and 
> if the idea that just by seeing "guard let" we should expect a non-Optional 
> is somehow diffused, I think it's better to eradicate it.
> 
> First of all, if I'm returning an optional from a throwing function, it's 
> probably the case that I want the Optional to be there in the returned value: 
> the only reason why I would consider doing that is if the semantics of 
> Optional are pretty meaningful in that case. For example, when parsing a JSON 
> in which I expect a String or null to be at a certain key:
> 
> 
> extension String: Error {}
> 
> func parseString(in dict: [String:Any], at key: String) throws -> String? {
>   guard let x = dict[key] else { throw "No value found at '\(key)' in 
> \(dict)" }
>   if let x = x as? String { return x }
>   if let x = x as? NSNull { return nil }
>   throw "Value at '\(key)' in \(dict) is not 'string' or 'null"
> }
> 
> 
> Thus, if I'm returning an Optional from a throwing function it means that I 
> want to clearly distinguish the two cases, so they shouldn't be collapsed in 
> a single call:
> 
> 
> guard let x = try doSomething() catch { /// handle and return }
> guard let x = x else { /// handle and return }
> 
> 
> Also, if a function returns something like "Int??", a guard-let (or if-let) 
> on the returned value of that function will still bind an "Int?", thus 
> unwrapping only "one level" of optional. If-let and guard-let, as of today, 
> just unwrap a single optional level, an do not guaranteed at all that the 
> bound value is not optional.
> 
> To me guard-let (like if-let) is basically sugar for monadic binding for 
> Optionals, with the additional expressivity granted by the forced return. I 
> would love to see the same monadic binding structure applied to throwing 
> functions.
> 
> 
> 
> Elviro
> 
> 
> 
>> Il giorno 09 lug 2017, alle ore 01:16, Christopher Kornher via 
>> swift-evolution > > ha scritto:
>> 
>> Thanks for you considerate reply. My concern over the proliferation of 
>> “sugar proposals” is a general one. This proposal has more merit and general 
>> utiliity than many others. I have never used a throwing function in a guard 
>> statement that was not itself in a throwing function, but I can see that it 
>> could possibly be common in some code. Wrapping a guard statement and all 
>> the code that uses variables set in the guard in a do/catch is sub-optimal.
>> 
>>> On Jul 8, 2017, at 4:16 PM, Benjamin Spratling via swift-evolution 
>>> > wrote:
>>> 
>>> 
>>> 
>>> I’ve read your email, but haven’t digested it fully.  One thing I agree 
>>> with is that most 

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

2017-07-10 Thread Elviro Rocca via swift-evolution
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 of people, including me. Rethrowing an error is something that I almost 
never do, and I consider the "umbrella" do/catch at the top of the call stack 
an anti-pattern, but I understand that many people like it and I'm not arguing 
against it. I am arguing in favor of having options and not pushing a 
particular style onto programmers, and for my (and many people's) style, a 
guard/catch with forced return is an excellent idea. In fact you seem to agree 
on the necessity of some kind of forced-returnish catch but your elaborations 
don't seem (to me) much better than the proposal itself.

Dave DeLong raised the point of weird behavior in the case of a function like:


func doSomething() throws → Result? { … }


In this case, what would the type of x be?


guard let x = try doSomething() catch { /// handle and return }


Simple, it would be Optional. I don't find this confusing at all, and 
if the idea that just by seeing "guard let" we should expect a non-Optional is 
somehow diffused, I think it's better to eradicate it.

First of all, if I'm returning an optional from a throwing function, it's 
probably the case that I want the Optional to be there in the returned value: 
the only reason why I would consider doing that is if the semantics of Optional 
are pretty meaningful in that case. For example, when parsing a JSON in which I 
expect a String or null to be at a certain key:


extension String: Error {}

func parseString(in dict: [String:Any], at key: String) throws -> String? {
guard let x = dict[key] else { throw "No value found at '\(key)' in 
\(dict)" }
if let x = x as? String { return x }
if let x = x as? NSNull { return nil }
throw "Value at '\(key)' in \(dict) is not 'string' or 'null"
}


Thus, if I'm returning an Optional from a throwing function it means that I 
want to clearly distinguish the two cases, so they shouldn't be collapsed in a 
single call:


guard let x = try doSomething() catch { /// handle and return }
guard let x = x else { /// handle and return }


Also, if a function returns something like "Int??", a guard-let (or if-let) on 
the returned value of that function will still bind an "Int?", thus unwrapping 
only "one level" of optional. If-let and guard-let, as of today, just unwrap a 
single optional level, an do not guaranteed at all that the bound value is not 
optional.

To me guard-let (like if-let) is basically sugar for monadic binding for 
Optionals, with the additional expressivity granted by the forced return. I 
would love to see the same monadic binding structure applied to throwing 
functions.



Elviro



> Il giorno 09 lug 2017, alle ore 01:16, Christopher Kornher via 
> swift-evolution  > ha scritto:
> 
> Thanks for you considerate reply. My concern over the proliferation of “sugar 
> proposals” is a general one. This proposal has more merit and general 
> utiliity than many others. I have never used a throwing function in a guard 
> statement that was not itself in a throwing function, but I can see that it 
> could possibly be common in some code. Wrapping a guard statement and all the 
> code that uses variables set in the guard in a do/catch is sub-optimal.
> 
>> On Jul 8, 2017, at 4:16 PM, Benjamin Spratling via swift-evolution 
>> > wrote:
>> 
>> 
>> 
>> I’ve read your email, but haven’t digested it fully.  One thing I agree with 
>> is that most functions which call throwing functions don’t actually use a 
>> do…catch block, but instead are merely marked “throws” and the error is 
>> propagated back through the stack.  Once I seriously started coding 
>> functions with errors, I realized I almost always wanted my errors to reach 
>> my view-controller or my business logic so I could present separate UI if a 
>> real error occurred, and often my error message depended on the details of 
>> the error instance.
>> 
>> 
>> 
>> I disagree with your conclusion on this point.
>> The “guard” syntax is specifically designed to achieve early return (and 
>> placing code associated with early return at the point where it happens) and 
>> cleanly installing the returned value into the surrounding scope.  So 

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

2017-07-09 Thread Charles Srstka via swift-evolution
> On Jul 8, 2017, at 3:08 PM, Christopher Kornher via swift-evolution 
>  wrote:
> 
> I am opposed to this proposal because it muddies up the language to support 
> what is essentially an edge case. The standard way to exit a function early 
> because an exception is thrown is to make the function itself throw, if it is 
> part of a larger operation. The addition of a few lines of try/catch code is 
> not a great burden and makes the termination of an an exception very clear.

Not such an edge case, if you write asynchronous code:

func doSomething(completionHandler: @escaping (Error?) -> ()) {
guard let foo = try makeFoo() catch {
completionHandler(error)
return
}

doSomeAsyncThing(with: foo) {
do {
try parseTheResult($0)
completionHandler(nil)
} catch {
completionHandler(error)
}
}
}

With the existing facilities, one must either use this rather awkward 
construction to make foo:

func doSomething(completionHandler: @escaping (Error?) -> ()) {
let foo: Foo

do {
foo = try makeFoo()
} catch {
completionHandler(error)
return
}

doSomeAsyncThing(with: foo) {
do {
try parseTheResult($0)
completionHandler(nil)
} catch {
completionHandler(error)
}
}
}

Or, alternatively, construct a pyramid of doom:

func doSomething(completionHandler: @escaping (Error?) -> ()) {
do {
let foo = try makeFoo()

doSomeAsyncThing(with: foo) {
do {
try parseTheResult($0)
completionHandler(nil)
} catch {
completionHandler(error)
}
}
} catch {
completionHandler(error)
}
}

Charles

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


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

2017-07-09 Thread Christopher Kornher via swift-evolution
I dashed these emails off very quickly, which is something I should never do 
here. There problems with the “trailing catch” idea. Some of them could be made 
to work, with enough rules added, but it would probably have been best to just 
stick with my original objection to adding special-case syntactic sugar at this 
point in the evolution of the language.

The "trailing catch” would be pretty straightforward for `try?` and `try!` 
calls, since both handle the lack of a return value from the called function. 
There is currently no way to do anything with exceptions thrown from `try?` and 
‘try!’, so there might be some value for these.`try` is more problematic and 
would require an exit or a or an exception to be thrown from the catch block. 
This adds more rules to ‘catch’, which argues against including it in the 
language. Another keyword like “intercept” for catches that would guarantee 
that an exception is thrown from the handling block would be a better choice 
for “try”, I think, but the bar for new keywords is justifiably very high.

In any case, the logic from all uses of a "trailing catch" can be replicated 
with nested do/catch blocks, so I do not think that these ideas should be 
considered now.

The “trailing catch” idea might fit with Dave DeLong’s suggestion of a few days 
ago, in which he wanted support for detailed diagnostics (hopefully that is a 
correct summary). If/when that topic ever is considered, then the "trailing 
catch” may have a place as part of that effort.


> On Jul 8, 2017, at 5:16 PM, Christopher Kornher via swift-evolution 
>  wrote:
> 
> Thanks for you considerate reply. My concern over the proliferation of “sugar 
> proposals” is a general one. This proposal has more merit and general 
> utiliity than many others. I have never used a throwing function in a guard 
> statement that was not itself in a throwing function, but I can see that it 
> could possibly be common in some code. Wrapping a guard statement and all the 
> code that uses variables set in the guard in a do/catch is sub-optimal.
> 
>> On Jul 8, 2017, at 4:16 PM, Benjamin Spratling via swift-evolution 
>> > wrote:
>> 
>> 
>>> On Jul 8, 2017, at 4:08 PM, Christopher Kornher >> > wrote:
>>> 
>>> I am opposed to this proposal because it muddies up the language to support 
>>> what is essentially an edge case. The standard way to exit a function early 
>>> because an exception is thrown is to make the function itself throw, if it 
>>> is part of a larger operation. The addition of a few lines of try/catch 
>>> code is not a great burden and makes the termination of an an exception 
>>> very clear.
>> 
>> I’ve read your email, but haven’t digested it fully.  One thing I agree with 
>> is that most functions which call throwing functions don’t actually use a 
>> do…catch block, but instead are merely marked “throws” and the error is 
>> propagated back through the stack.  Once I seriously started coding 
>> functions with errors, I realized I almost always wanted my errors to reach 
>> my view-controller or my business logic so I could present separate UI if a 
>> real error occurred, and often my error message depended on the details of 
>> the error instance.
>> 
>>> `guard` statements are generally used to set variables that are needed in 
>>> the body of a function. Using them to save a few lines of exception handing 
>>> code is a very different use. There is no need to mix two relatively clean 
>>> syntaxes for a few edge cases and increase cognitive load one more time, 
>> 
>> 
>> I disagree with your conclusion on this point.
>> The “guard” syntax is specifically designed to achieve early return (and 
>> placing code associated with early return at the point where it happens) and 
>> cleanly installing the returned value into the surrounding scope.  So far it 
>> has been used to achieve early return only with optionals, true.  But is 
>> that inherent to ‘guard’, or is it merely because that’s the only way it has 
>> been used?  The guard does set variables that are needed in the body of the 
>> function, and that’s exactly why using guard with values returned from 
>> throwing functions makes so much sense, because it does exactly the same 
>> thing in a general sense.  The “do”…”catch” structure is intentionally 
>> designed differently, to place the “happy path” in one place and place the 
>> returns in another place.  I think with guard/else, we’re seeing developers 
>> who can handle less cognitive loading find it easier to reason about early 
>> return than grouping failures after the happy path.  This proposal hopes to 
>> introduce that better language architecture to the catching of errors.
> 
> All catches don’t have to exit the outer scope, so using guard only handles a 
> subset 
> 
> It think that creating the terse try/catch for simple cases has multiple 
> 

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

2017-07-08 Thread Christopher Kornher via swift-evolution
Thanks for you considerate reply. My concern over the proliferation of “sugar 
proposals” is a general one. This proposal has more merit and general utiliity 
than many others. I have never used a throwing function in a guard statement 
that was not itself in a throwing function, but I can see that it could 
possibly be common in some code. Wrapping a guard statement and all the code 
that uses variables set in the guard in a do/catch is sub-optimal.

> On Jul 8, 2017, at 4:16 PM, Benjamin Spratling via swift-evolution 
>  wrote:
> 
> 
>> On Jul 8, 2017, at 4:08 PM, Christopher Kornher  wrote:
>> 
>> I am opposed to this proposal because it muddies up the language to support 
>> what is essentially an edge case. The standard way to exit a function early 
>> because an exception is thrown is to make the function itself throw, if it 
>> is part of a larger operation. The addition of a few lines of try/catch code 
>> is not a great burden and makes the termination of an an exception very 
>> clear.
> 
> I’ve read your email, but haven’t digested it fully.  One thing I agree with 
> is that most functions which call throwing functions don’t actually use a 
> do…catch block, but instead are merely marked “throws” and the error is 
> propagated back through the stack.  Once I seriously started coding functions 
> with errors, I realized I almost always wanted my errors to reach my 
> view-controller or my business logic so I could present separate UI if a real 
> error occurred, and often my error message depended on the details of the 
> error instance.
> 
>> `guard` statements are generally used to set variables that are needed in 
>> the body of a function. Using them to save a few lines of exception handing 
>> code is a very different use. There is no need to mix two relatively clean 
>> syntaxes for a few edge cases and increase cognitive load one more time, 
> 
> 
> I disagree with your conclusion on this point.
> The “guard” syntax is specifically designed to achieve early return (and 
> placing code associated with early return at the point where it happens) and 
> cleanly installing the returned value into the surrounding scope.  So far it 
> has been used to achieve early return only with optionals, true.  But is that 
> inherent to ‘guard’, or is it merely because that’s the only way it has been 
> used?  The guard does set variables that are needed in the body of the 
> function, and that’s exactly why using guard with values returned from 
> throwing functions makes so much sense, because it does exactly the same 
> thing in a general sense.  The “do”…”catch” structure is intentionally 
> designed differently, to place the “happy path” in one place and place the 
> returns in another place.  I think with guard/else, we’re seeing developers 
> who can handle less cognitive loading find it easier to reason about early 
> return than grouping failures after the happy path.  This proposal hopes to 
> introduce that better language architecture to the catching of errors.

All catches don’t have to exit the outer scope, so using guard only handles a 
subset 

It think that creating the terse try/catch for simple cases has multiple 
advantages:

1) I think that it addresses your desire for a simple way to use 
throwing functions easily in guard statements.

2) It avoids having to change the guard syntax to accomplish this

3) It is useful for handling simple one line try/catch constructs in 
less space in a way that should not seem too foreign to Swift developers.

4) It simplifies code that currently uses nested do/try/catch 
constructs. Even though this is rare, it introduces significant “rightward 
drift”.

5) It can used to return early from void throwing functions easily. 
e.g. : 

```
guard try foo( ) catch { return }
```

Multiple void throwing functions would probably be better handled by a 
do/catch block, but there is no danger of needing values from these functions 
because there are none:

```
do {
try fn1()
try fn2()
} catch {
// keep going, return or call a non-returning function, since 
throw is already handled by declaring a throwing enclosing function.
// No varibles are needed by the outer block because none are 
set
// So it is not clearly a guard-like statement
}
```

I did not think of this before, but perhaps we could allow `do` to be 
replaced with `guard`, thereby allowing values to escape to the outer scope, 
while still ensuring an early exit:

```
guard {
try fn1()
try fn2()
let x = fn3()
} catch {
// Must exit
} else {
// Must exit
}
```
I am not sure that “leaky” braces are a 

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

2017-07-08 Thread Benjamin Spratling via swift-evolution

> On Jul 8, 2017, at 4:08 PM, Christopher Kornher  wrote:
> 
> I am opposed to this proposal because it muddies up the language to support 
> what is essentially an edge case. The standard way to exit a function early 
> because an exception is thrown is to make the function itself throw, if it is 
> part of a larger operation. The addition of a few lines of try/catch code is 
> not a great burden and makes the termination of an an exception very clear.

I’ve read your email, but haven’t digested it fully.  One thing I agree with is 
that most functions which call throwing functions don’t actually use a do…catch 
block, but instead are merely marked “throws” and the error is propagated back 
through the stack.  Once I seriously started coding functions with errors, I 
realized I almost always wanted my errors to reach my view-controller or my 
business logic so I could present separate UI if a real error occurred, and 
often my error message depended on the details of the error instance.

> `guard` statements are generally used to set variables that are needed in the 
> body of a function. Using them to save a few lines of exception handing code 
> is a very different use. There is no need to mix two relatively clean 
> syntaxes for a few edge cases and increase cognitive load one more time, 


I disagree with your conclusion on this point.
The “guard” syntax is specifically designed to achieve early return (and 
placing code associated with early return at the point where it happens) and 
cleanly installing the returned value into the surrounding scope.  So far it 
has been used to achieve early return only with optionals, true.  But is that 
inherent to ‘guard’, or is it merely because that’s the only way it has been 
used?  The guard does set variables that are needed in the body of the 
function, and that’s exactly why using guard with values returned from throwing 
functions makes so much sense, because it does exactly the same thing in a 
general sense.  The “do”…”catch” structure is intentionally designed 
differently, to place the “happy path” in one place and place the returns in 
another place.  I think with guard/else, we’re seeing developers who can handle 
less cognitive loading find it easier to reason about early return than 
grouping failures after the happy path.  This proposal hopes to introduce that 
better language architecture to the catching of errors.

-Ben Spratling

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


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

2017-07-08 Thread Christopher Kornher via swift-evolution
I am opposed to this proposal because it muddies up the language to support 
what is essentially an edge case. The standard way to exit a function early 
because an exception is thrown is to make the function itself throw, if it is 
part of a larger operation. The addition of a few lines of try/catch code is 
not a great burden and makes the termination of an an exception very clear.

`guard` statements are generally used to set variables that are needed in the 
body of a function. Using them to save a few lines of exception handing code is 
a very different use. There is no need to mix two relatively clean syntaxes for 
a few edge cases and increase cognitive load one more time, 

If we really want a more compact try/catch syntax, we should not use (abuse?) 
the `guard` statement, but instead allow a training catch which reads similarly 
to a trailing closure:

```
let x = try aFunction() catch ( let e: Error ) {
… 
} 

```

This might be confused with trailing closures, but since most editors will 
highlight the `catch`, the meaning should be pretty clear.


Using this in a `guard` would look like: 

```
guard let x = try aFunction() catch ( let e: Error ) { … // must exit };
let y=y;
let z=x else {
...
}
```
Multiple throwing statements in the guard could be handled like:

```
guard let x = try aFunction();
let xx = try aFunction2() catch ( let e: Error ) { … // must exit };
let y=y;
let z=x else {
...
}
```
but this creeps toward the original proposal and I do not think that the added 
complexity is worth the trouble. I prefer the simpler syntax for the rare cases 
where is more than one throwing statement within the guard:

```
guard let x = try aFunction() catch ( let e: Error ) { … // must exit };
let xx = try aFunction2() catch ( let e: Error ) { … // must exit };
let y=y;
let z=x else {
...
}
```

This addition, I believe, adds much more power to the language and retains the 
simplicity of the “guard” statement.


It helps clean-up code like:

```
func attemptComplexOperation() throws {
do {
let x = try functionA()
} catch ( let e: Error ) {
Log.error( “could not do A: \(String(describing:e)” )
throw e
}

do {
let y = try functionB()
} catch ( let e: Error ) {
Log.error( “could not do B: \(String(describing:e)” )
throw e
}
}
```

to:

```
func attemptComplexOperation() throws {
let x = try functionA() catch ( let e: Error ) {
Log.error( “could not do A: \(String(describing:e)” )
throw e
}

let Y = try functionB() catch ( let e: Error ) {
Log.error( “could not do B: \(String(describing:e)” )
throw e
}
}
```

This this is error-prone because exception rethrowing could be omitted and the 
code would still compile. Perhaps another keyword to act upon an exception, but 
not consume it would be useful (I am sure that this idea will be popular :) )

```
func attemptComplexOperation() throws {
let x = try functionA() intercept ( let e: Error ) {
Log.error( “could not do A: \(String(describing:e)” )
}

let Y = try functionB() intercept ( let e: Error ) {
Log.error( “could not do B: \(String(describing:e)” )
}
}
```

I hope that the themes for Swift 5 comes soon from the core team, so we can 
slow down the discussions of the 'syntactic sugar proposal of the week'. I fear 
that Swift will become a much more complex and difficult to read language if we 
keep adding sugar to handle special cases. I hope that it doesn’t become too 
difficult to understand through all the special-case sugar coating. Perhaps 
more importantly, there are important features awaiting implementation that are 
needed by members of the community that will be delayed and possibly 
complicated by the addition of syntactic sugar.

If the decision is to accept the original proposal, then I vote for #1 below. 
Note that exceptions could be handled within the else clause by changing the 
order. I don’t think that this would be a good idea, however, as it makes the 
statement even harder to understand:


Please, not this:
```
guard let result:Result = try doSomething()
else {  try cleanup() }
catch { ...}
```


> On Jul 8, 2017, at 12:15 PM, Benjamin Spratling via swift-evolution 
>  wrote:
> 
> 
>> func doSomething() throws → Result? { … }
>> 
>> How would you handle both the catch and the let binding of the result?
> 
> I agree this proposal needs to define the behavior, since returning an 
> optional from a throwing function is valid.
> 
> I see a few options:
> 
> 1) find a way to generally incorporate optional binding and error binding 
> into the same guard clause.
> Could it be as simple as 
> guard let result:Result = try doSomething()
> catch { ...}
> else { ... }
> ?
> 
>  In this option, the else block almost acts like "finally" block.  I 
> recommend against this option because IF 

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

2017-07-08 Thread Xiaodi Wu via swift-evolution
On Sat, Jul 8, 2017 at 2:11 PM, Benjamin Spratling via swift-evolution <
swift-evolution@swift.org> wrote:

>
> func doSomething() throws → Result? { … }
>
> How would you handle both the catch and the let binding of the result?
>
>
> I agree this proposal needs to define the behavior, since returning an
> optional from a throwing function is valid.
>
> I see a few options:
>
> 1) find a way to generally incorporate optional binding and error binding
> into the same guard clause.
> Could it be as simple as
> guard let result:Result = try doSomething()
> catch { ...}
> else { ... }
> ?
>
>  In this option, the else block almost acts like "finally" block.  I
> recommend against this option because IF the developer has defined a
> function which returns nil and doesn't throw an error, they clearly intend
> for the nil to be a valid representation of state, and thus one the
> developer may wish to examine in more detail and potentially continue the
> function. I. E. Let's give the developer a chance to work with the nil
> value and not return.
>
> 2) Ignore it completely.  I.e. define the guard/catch pattern as not
> compatible with returning Optionals.  Throwing an error is usually
> considered an alternative to returning an optional, and importing Obj-C
> won't import throwing methods in this way. So I don't think prohibiting it
> is a totally absurd idea.  This makes it impossible for the developer to
> code and build code which accidentally does something he doesn't expect.
>
> 3) bind the optional value
>
> Perhaps, when guard/catch-ing, an optional value is perfectly legal.
>
> guard let result:Result? = try doSomething() catch ...
> This is essentially how guard works with a try?today.
> guard let result:Result? = try? doSomething() ...
>
> In case 3, I think we have a potentially ambiguous behavior, because with
> type inference the programmer may expect that the value has also been
> optionally unwrapped.  Of course, he'll catch that later on in the
> function, but my concern is for the poor unwitting developer (such as
> myself) who is frustrated that his code doesn't compile and he doesn't
> understand why.  "But I did a guard let!   Why is it optional?!"  One
> option is to require the type be typed explicitly when guard/catching an
> optional, but I always type my types explicitly anyway, so I get that
> others may be more resistant to that idea.  Another option is to allow it,
> but just issue a warning until the developer adds the explicit type, such
> as requiring "self." in an escaping closure.  (Of course the compler can
> figure it out, this syntax is required so the developer can figure it out!)
>  Another option is for the smarts to be built in the the error/warning
> system to point out when an expression gets used as a non-optional when it
> came from a guard/catch to point it out, much as it points out the first
> instance of a function which has been defined twice.
>

Agree that (3) is potentially ambiguous and has high likelihood to be a
footgun.

Also agree that _if_ the developer defines a function that can return nil
*and* can throw an error, nil is likely to be a bona fide representation of
state. One possibility--with an obvious problem (see below)--is therefore
to have the successful result of guard...catch be of type `Result?`:

```
guard let result = try doSomething() catch { ... }
guard let unwrappedResult = result else { ... }
```

The obvious problem is that `guard let` in Swift is closely associated with
optional unwrapping. The reader is right to expect a non-optional `result`
with `guard let` regardless of the word that comes after conditional
expression. There are two ways to see this:

One way is: If we consider `doSomething() throws -> Result?` to be a
function where throwing indicates that the operation has failed and nil is
a bona fide representation of state, then it can be seen as a function more
similar to `doSomethingElse() -> Result??`, where the outer Optional
indicates whether the operation succeeded (see Swift error handling
rationale document) and the inner Optional is a bona fide representation of
state. Therefore, just as `guard let result = doSomethingElse() else { ...
}` gives you a result of type `Result?`, so should `guard let result = try
doSomething() catch { ... }`.

However, I can see how this might be confusing to users. The fundamental
problem here is one of spelling, where users instinctively see `guard let`
and expect one level of optional unwrapping. This idea is reinforced
because `guard...else` does *not* permit `guard let` when the result isn't
optional. Therefore, another way to solve this issue is to make this rule
also apply to `guard...catch`. That is, make the syntax of `guard...catch`
_not_ use `guard let` unless the result is optional:

```
let result: Result?
guard result = try doSomething() catch { ... }
```

However, though it does solve the stated motivation of removing one level
of braces, this form of `guard...else` is hardly 

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

2017-07-08 Thread Benjamin Spratling via swift-evolution

> func doSomething() throws → Result? { … }
> 
> How would you handle both the catch and the let binding of the result?

I agree this proposal needs to define the behavior, since returning an optional 
from a throwing function is valid.

I see a few options:

1) find a way to generally incorporate optional binding and error binding into 
the same guard clause.
Could it be as simple as 
guard let result:Result = try doSomething()
catch { ...}
else { ... }
?

 In this option, the else block almost acts like "finally" block.  I recommend 
against this option because IF the developer has defined a function which 
returns nil and doesn't throw an error, they clearly intend for the nil to be a 
valid representation of state, and thus one the developer may wish to examine 
in more detail and potentially continue the function. I. E. Let's give the 
developer a chance to work with the nil value and not return.

2) Ignore it completely.  I.e. define the guard/catch pattern as not compatible 
with returning Optionals.  Throwing an error is usually considered an 
alternative to returning an optional, and importing Obj-C won't import throwing 
methods in this way. So I don't think prohibiting it is a totally absurd idea.  
This makes it impossible for the developer to code and build code which 
accidentally does something he doesn't expect.

3) bind the optional value

Perhaps, when guard/catch-ing, an optional value is perfectly legal.

guard let result:Result? = try doSomething() catch ...
This is essentially how guard works with a try?today.
guard let result:Result? = try? doSomething() ...

In case 3, I think we have a potentially ambiguous behavior, because with type 
inference the programmer may expect that the value has also been optionally 
unwrapped.  Of course, he'll catch that later on in the function, but my 
concern is for the poor unwitting developer (such as myself) who is frustrated 
that his code doesn't compile and he doesn't understand why.  "But I did a 
guard let!   Why is it optional?!"  One option is to require the type be typed 
explicitly when guard/catching an optional, but I always type my types 
explicitly anyway, so I get that others may be more resistant to that idea.  
Another option is to allow it, but just issue a warning until the developer 
adds the explicit type, such as requiring "self." in an escaping closure.  (Of 
course the compler can figure it out, this syntax is required so the developer 
can figure it out!)  Another option is for the smarts to be built in the the 
error/warning system to point out when an expression gets used as a 
non-optional when it came from a guard/catch to point it out, much as it points 
out the first instance of a function which has been defined twice.


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


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

2017-07-07 Thread Dave DeLong via swift-evolution
What about the situation where you have:

func doSomething() throws → Result? { … }

How would you handle both the catch and the let binding of the result?

Dave

> On Jul 7, 2017, at 7:55 AM, Elviro Rocca via swift-evolution 
>  wrote:
> 
> Amazing proposal, I love it and thinking back there's plenty of times where I 
> would have used the guard-catch instead of the non-swifty (to me) do-catch. A 
> guard-catch construct still allows to handle errors explicitly, with the 
> added convenience of forcing a return inside the catch, which is basically 
> 100% of the cases for me. It's consistent with the semantics of "guard", that 
> is, instead of indenting, exit the scope in the "negative" case.
> 
> I do not agree in mixing guard-catch with optional binding (+ bool 
> conditions). I think it's clearer to keep the two separated, since you can 
> always:
> 
> guard let x = try throwingFunction() catch { ... }
> guard let y = x.optionalProperty, y == 42 else { ... }
> 
> 
> Thanks
> 
> 
> Elviro
> 
>> Il giorno 05 lug 2017, alle ore 19:40, Soroush Khanlou via swift-evolution 
>> > ha scritto:
>> 
>> I’d like to propose a guard/catch construct to the language. It would allow 
>> code to use throwing functions and handle errors fully, without straying 
>> from a happy path. do/catch can be a bit heavy-handed sometimes, and it 
>> would be nice to be able to handle throwing functions without committing to 
>> all the nesting and ceremony of do/catch.
>> 
>> Full proposal, which discusses all the corner cases and alternatives:
>> https://gist.github.com/khanlou/8bd9c6f46e2b3d94f0e9f037c775f5b9 
>> 
>> 
>> Looking forward to feedback!
>> 
>> Soroush
>> ___
>> 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] Guard/Catch

2017-07-07 Thread Elviro Rocca via swift-evolution
Amazing proposal, I love it and thinking back there's plenty of times where I 
would have used the guard-catch instead of the non-swifty (to me) do-catch. A 
guard-catch construct still allows to handle errors explicitly, with the added 
convenience of forcing a return inside the catch, which is basically 100% of 
the cases for me. It's consistent with the semantics of "guard", that is, 
instead of indenting, exit the scope in the "negative" case.

I do not agree in mixing guard-catch with optional binding (+ bool conditions). 
I think it's clearer to keep the two separated, since you can always:

guard let x = try throwingFunction() catch { ... }
guard let y = x.optionalProperty, y == 42 else { ... }


Thanks


Elviro

> Il giorno 05 lug 2017, alle ore 19:40, Soroush Khanlou via swift-evolution 
> > ha scritto:
> 
> I’d like to propose a guard/catch construct to the language. It would allow 
> code to use throwing functions and handle errors fully, without straying from 
> a happy path. do/catch can be a bit heavy-handed sometimes, and it would be 
> nice to be able to handle throwing functions without committing to all the 
> nesting and ceremony of do/catch.
> 
> Full proposal, which discusses all the corner cases and alternatives:
> https://gist.github.com/khanlou/8bd9c6f46e2b3d94f0e9f037c775f5b9 
> 
> 
> Looking forward to feedback!
> 
> Soroush
> ___
> 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] Guard/Catch

2017-07-05 Thread Benjamin Spratling via swift-evolution
Howdy,
I love it!  The “do" blocks never did “feel” like Swift.  I can see how 
both would be useful.
I like to use as many conditionals in a single guard statement as I can 
get away with, so I was concerned that guard/catch would need to interoperate 
with guard/else.  However, I am fairly convinced that, at least for now, having 
to choose between guard /catch and guard /else is not that much of a problem.  
guard/catch appears optimized for the simple-call case, where there is a single 
throwing expression, so the code can handle its specific error/s more 
precisely.  When catching anything in a batch is the goal, then a do block is 
probably fine.
-Ben

> On Jul 5, 2017, at 1:30 PM, Soroush Khanlou via swift-evolution 
>  wrote:
> 
> I’d like to propose a guard/catch construct to the language. It would allow 
> code to use throwing functions and handle errors fully, without straying from 
> a happy path. do/catch can be a bit heavy-handed sometimes, and it would be 
> nice to be able to handle throwing functions without committing to all the 
> nesting and ceremony of do/catch.
> 
> Full proposal, which discusses all the corner cases and alternatives:
> https://gist.github.com/khanlou/8bd9c6f46e2b3d94f0e9f037c775f5b9 
> 
> 
> Looking forward to feedback!
> 
> Soroush
> ___
> 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] Guard/Catch

2017-07-05 Thread Zach Waldowski via swift-evolution
I second Xiaodi on this. The syntax feels like a slam-dunk. The only
concerns I have are indentation, and ultimately that's not my problem to
decide about. ;)
Sincerely,
  Zachary Waldowski
  z...@waldowski.me

On Wed, Jul 5, 2017, at 07:15 PM, Xiaodi Wu via swift-evolution wrote:
> Initially, this proposal felt a little off, but on re-reading, I think
> I like it very much. It shows that guard/catch is meant to solve a
> nesting problem (just like guard/else was meant to solve one), and it
> preserves the idea that the else/catch clause must exit the outer
> scope, which is very important to the meaning of `guard`.> 
> I agree with the proposal authors that mix-and-match guard/catch/else
> feels unwise. I see no reason why rewriting to repeat only the word
> `guard` (as in, `guard A catch { }; guard B else { }` instead of
> `guard A, B catch { } else { }`) is onerous enough to justify a syntax
> that is clearly harder to reason about.> 
> On Wed, Jul 5, 2017 at 2:25 PM, Soroush Khanlou via swift-evolution
>  wrote:>> Jon — we explored allowing users to mix 
> and match optional unwrapping
>> and error catching in the same guard, but found that it was
>> ultimately pretty confusing. We think that guard/else and guard/catch
>> should be two totally different components. Dave’s email lays out the
>> two best approaches, and the “Alternatives Considered” section of the
>> proposal goes into why those alternatives were ultimately rejected.>> 
>>> On Jul 5, 2017, at 2:09 PM, Dave DeLong via swift-evolution >> evolut...@swift.org> wrote:>>> 
>>> Soroush’s proposal has the idea that maybe we could do multiple
>>> blocks for this scenario, like so:>>> 
>>> guard try something(), let thing = optionalThing catch {
>>> // try something() failed
>>> } else {
>>> // the let-binding failed
>>> }
>>> 
>>> 樂 Alternatively, what if the “error” captured was optional in this
>>> scenario?>>> 
>>> guard try something(), let thing = optionalThing catch {
>>> if let error = error {
>>> // the try call failed
>>> } else {
>>> // the optional binding failed
>>> }
>>> }
>>> 
>>> Dave
>>> 
 On Jul 5, 2017, at 12:00 PM, Jon Shier via swift-evolution >>> evolut...@swift.org> wrote: 
 I didn’t think I was going to like it but I really do. My only
 concern, which isn’t really a deal breaker, is what it would look
 like to chain multiple try and let statement in the same guard.
 Unless that scenario works well I don’t think you could convince
 others. i.e. In the case where I have: 
 guard try something(), let thing = optionalThing catch { }
 
 What happens when the let fails? No implicit error?
 
 
 
 Jon
 
 
> On Jul 5, 2017, at 1:30 PM, Soroush Khanlou via swift-evolution
>  wrote:> 
> I’d like to propose a guard/catch construct to the language. It
> would allow code to use throwing functions and handle errors
> fully, without straying from a happy path. do/catch can be a bit
> heavy-handed sometimes, and it would be nice to be able to handle
> throwing functions without committing to all the nesting and
> ceremony of do/catch.> 
> Full proposal, which discusses all the corner cases and
> alternatives:> 
> https://gist.github.com/khanlou/8bd9c6f46e2b3d94f0e9f037c775f5b9
> 
> Looking forward to feedback!
> 
> Soroush
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
 
 ___
 swift-evolution mailing list
 swift-evolution@swift.org
 https://lists.swift.org/mailman/listinfo/swift-evolution
>>> 
>>> ___
>>> swift-evolution mailing list
>>> swift-evolution@swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> 
>> 
>> ___
>>  swift-evolution mailing list
>> swift-evolution@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> 
> _
> 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] Guard/Catch

2017-07-05 Thread Xiaodi Wu via swift-evolution
Initially, this proposal felt a little off, but on re-reading, I think I
like it very much. It shows that guard/catch is meant to solve a nesting
problem (just like guard/else was meant to solve one), and it preserves the
idea that the else/catch clause must exit the outer scope, which is very
important to the meaning of `guard`.

I agree with the proposal authors that mix-and-match guard/catch/else feels
unwise. I see no reason why rewriting to repeat only the word `guard` (as
in, `guard A catch { }; guard B else { }` instead of `guard A, B catch { }
else { }`) is onerous enough to justify a syntax that is clearly harder to
reason about.

On Wed, Jul 5, 2017 at 2:25 PM, Soroush Khanlou via swift-evolution <
swift-evolution@swift.org> wrote:

> Jon — we explored allowing users to mix and match optional unwrapping and
> error catching in the same guard, but found that it was ultimately pretty
> confusing. We think that guard/else and guard/catch should be two totally
> different components. Dave’s email lays out the two best approaches, and
> the “Alternatives Considered” section of the proposal goes into why those
> alternatives were ultimately rejected.
>
> On Jul 5, 2017, at 2:09 PM, Dave DeLong via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> Soroush’s proposal has the idea that maybe we could do multiple blocks for
> this scenario, like so:
>
> guard try something(), let thing = optionalThing catch {
> // try something() failed
> } else {
> // the let-binding failed
> }
>
> 樂 Alternatively, what if the “error” captured was optional in this
> scenario?
>
> guard try something(), let thing = optionalThing catch {
> if let error = error {
> // the try call failed
> } else {
> // the optional binding failed
> }
> }
>
> Dave
>
> On Jul 5, 2017, at 12:00 PM, Jon Shier via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> I didn’t think I was going to like it but I really do. My only concern,
> which isn’t really a deal breaker, is what it would look like to chain
> multiple try and let statement in the same guard. Unless that scenario
> works well I don’t think you could convince others. i.e. In the case where
> I have:
>
> guard try something(), let thing = optionalThing catch { }
>
> What happens when the let fails? No implicit error?
>
>
>
> Jon
>
>
> On Jul 5, 2017, at 1:30 PM, Soroush Khanlou via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> I’d like to propose a guard/catch construct to the language. It would
> allow code to use throwing functions and handle errors fully, without
> straying from a happy path. do/catch can be a bit heavy-handed sometimes,
> and it would be nice to be able to handle throwing functions without
> committing to all the nesting and ceremony of do/catch.
>
> Full proposal, which discusses all the corner cases and alternatives:
> https://gist.github.com/khanlou/8bd9c6f46e2b3d94f0e9f037c775f5b9
>
> Looking forward to feedback!
>
> Soroush
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
>
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


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

2017-07-05 Thread Soroush Khanlou via swift-evolution
Jon — we explored allowing users to mix and match optional unwrapping and error 
catching in the same guard, but found that it was ultimately pretty confusing. 
We think that guard/else and guard/catch should be two totally different 
components. Dave’s email lays out the two best approaches, and the 
“Alternatives Considered” section of the proposal goes into why those 
alternatives were ultimately rejected.

> On Jul 5, 2017, at 2:09 PM, Dave DeLong via swift-evolution 
>  wrote:
> 
> Soroush’s proposal has the idea that maybe we could do multiple blocks for 
> this scenario, like so:
> 
> guard try something(), let thing = optionalThing catch {
> // try something() failed
> } else {
> // the let-binding failed
> }
> 
> 樂 Alternatively, what if the “error” captured was optional in this scenario?
> 
> guard try something(), let thing = optionalThing catch {
> if let error = error {
> // the try call failed
> } else {
> // the optional binding failed
> }
> }
> 
> Dave
> 
>> On Jul 5, 2017, at 12:00 PM, Jon Shier via swift-evolution 
>> > wrote:
>> 
>>  I didn’t think I was going to like it but I really do. My only concern, 
>> which isn’t really a deal breaker, is what it would look like to chain 
>> multiple try and let statement in the same guard. Unless that scenario works 
>> well I don’t think you could convince others. i.e. In the case where I have:
>> 
>> guard try something(), let thing = optionalThing catch { }
>> 
>> What happens when the let fails? No implicit error?
>> 
>> 
>> 
>> Jon
>> 
>> 
>>> On Jul 5, 2017, at 1:30 PM, Soroush Khanlou via swift-evolution 
>>> > wrote:
>>> 
>>> I’d like to propose a guard/catch construct to the language. It would allow 
>>> code to use throwing functions and handle errors fully, without straying 
>>> from a happy path. do/catch can be a bit heavy-handed sometimes, and it 
>>> would be nice to be able to handle throwing functions without committing to 
>>> all the nesting and ceremony of do/catch.
>>> 
>>> Full proposal, which discusses all the corner cases and alternatives:
>>> https://gist.github.com/khanlou/8bd9c6f46e2b3d94f0e9f037c775f5b9 
>>> 
>>> 
>>> Looking forward to feedback!
>>> 
>>> Soroush
>>> ___
>>> swift-evolution mailing list
>>> swift-evolution@swift.org 
>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>> 
>> 
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org 
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

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


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

2017-07-05 Thread Beta via swift-evolution


> On Jul 5, 2017, at 10:30 AM, Soroush Khanlou via swift-evolution 
>  wrote:
> 
> I’d like to propose a guard/catch construct to the language. It would allow 
> code to use throwing functions and handle errors fully, without straying from 
> a happy path. do/catch can be a bit heavy-handed sometimes, and it would be 
> nice to be able to handle throwing functions without committing to all the 
> nesting and ceremony of do/catch.
> 

The nesting and ceremony, to me, were part of Swift’s philosophy of making 
error handling explicit.  Merging catch blocks into guards saves you maybe 3-10 
lines if you intended to actually handle the error(s), otherwise this 
effectively try?’s  into a failable pattern match.  At which point, you have to 
wonder if the error-throwing function you wrote wouldn’t be better off just 
returning an Optional if you’re going to discard the semantic content of the 
error.

~Robert Widmann

> Full proposal, which discusses all the corner cases and alternatives:
> https://gist.github.com/khanlou/8bd9c6f46e2b3d94f0e9f037c775f5b9 
> 
> 
> Looking forward to feedback!
> 
> Soroush
> ___
> 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] Guard/Catch

2017-07-05 Thread Dave DeLong via swift-evolution
Soroush’s proposal has the idea that maybe we could do multiple blocks for this 
scenario, like so:

guard try something(), let thing = optionalThing catch {
// try something() failed
} else {
// the let-binding failed
}

樂 Alternatively, what if the “error” captured was optional in this scenario?

guard try something(), let thing = optionalThing catch {
if let error = error {
// the try call failed
} else {
// the optional binding failed
}
}

Dave

> On Jul 5, 2017, at 12:00 PM, Jon Shier via swift-evolution 
>  wrote:
> 
>   I didn’t think I was going to like it but I really do. My only concern, 
> which isn’t really a deal breaker, is what it would look like to chain 
> multiple try and let statement in the same guard. Unless that scenario works 
> well I don’t think you could convince others. i.e. In the case where I have:
> 
> guard try something(), let thing = optionalThing catch { }
> 
> What happens when the let fails? No implicit error?
> 
> 
> 
> Jon
> 
> 
>> On Jul 5, 2017, at 1:30 PM, Soroush Khanlou via swift-evolution 
>> > wrote:
>> 
>> I’d like to propose a guard/catch construct to the language. It would allow 
>> code to use throwing functions and handle errors fully, without straying 
>> from a happy path. do/catch can be a bit heavy-handed sometimes, and it 
>> would be nice to be able to handle throwing functions without committing to 
>> all the nesting and ceremony of do/catch.
>> 
>> Full proposal, which discusses all the corner cases and alternatives:
>> https://gist.github.com/khanlou/8bd9c6f46e2b3d94f0e9f037c775f5b9 
>> 
>> 
>> Looking forward to feedback!
>> 
>> Soroush
>> ___
>> 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] Guard/Catch

2017-07-05 Thread Jon Shier via swift-evolution
I didn’t think I was going to like it but I really do. My only concern, 
which isn’t really a deal breaker, is what it would look like to chain multiple 
try and let statement in the same guard. Unless that scenario works well I 
don’t think you could convince others. i.e. In the case where I have:

guard try something(), let thing = optionalThing catch { }

What happens when the let fails? No implicit error?



Jon


> On Jul 5, 2017, at 1:30 PM, Soroush Khanlou via swift-evolution 
>  wrote:
> 
> I’d like to propose a guard/catch construct to the language. It would allow 
> code to use throwing functions and handle errors fully, without straying from 
> a happy path. do/catch can be a bit heavy-handed sometimes, and it would be 
> nice to be able to handle throwing functions without committing to all the 
> nesting and ceremony of do/catch.
> 
> Full proposal, which discusses all the corner cases and alternatives:
> https://gist.github.com/khanlou/8bd9c6f46e2b3d94f0e9f037c775f5b9 
> 
> 
> Looking forward to feedback!
> 
> Soroush
> ___
> 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] Guard/Catch

2017-07-05 Thread Jacob Bandes-Storch via swift-evolution
Some prior, probably not as well thought-through, discussion on this topic:
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160229/011446.html
On Wed, Jul 5, 2017 at 10:40 AM Soroush Khanlou via swift-evolution <
swift-evolution@swift.org> wrote:

> I’d like to propose a guard/catch construct to the language. It would
> allow code to use throwing functions and handle errors fully, without
> straying from a happy path. do/catch can be a bit heavy-handed sometimes,
> and it would be nice to be able to handle throwing functions without
> committing to all the nesting and ceremony of do/catch.
>
> Full proposal, which discusses all the corner cases and alternatives:
> https://gist.github.com/khanlou/8bd9c6f46e2b3d94f0e9f037c775f5b9
>
> Looking forward to feedback!
>
> Soroush
> ___
> 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] Guard/Catch

2017-07-05 Thread Soroush Khanlou via swift-evolution
I’d like to propose a guard/catch construct to the language. It would allow 
code to use throwing functions and handle errors fully, without straying from a 
happy path. do/catch can be a bit heavy-handed sometimes, and it would be nice 
to be able to handle throwing functions without committing to all the nesting 
and ceremony of do/catch.

Full proposal, which discusses all the corner cases and alternatives:
https://gist.github.com/khanlou/8bd9c6f46e2b3d94f0e9f037c775f5b9 


Looking forward to feedback!

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