The error handler doesn't have to be co-linear or even defined in the same call:
/// consists of filename, line number, error tuple
public typealias CommonErrorHandlerType = (String, Int, ErrorType) -> Void
/// Default error handler prints context and error
public let defaultCommonErrorHandler: CommonErrorHandlerType = {
filePath, lineNumber, error in
let trimmedFileName: String = (filePath as NSString).lastPathComponent
print("Error \(trimmedFileName):\(lineNumber) \(error)")
}
If you're doing much more than printing or adding a line-or-two extra then
I don't think you should be using guard, you should be applying do-catch at the
call site
or using try (not try? or try!) and forwarding the error handling.
-- E
> On Mar 23, 2016, at 8:05 AM, Maximilian Hünenberger <[email protected]>
> wrote:
>
> Your "attempt" function addresses this issue if someone only wants to print
> the error:
>
> guard let x = attempt({ try throwingFunction(y) }) else {
> return
> }
> // prints "Error \(trimmedFileName):\(lineNumber) \(error)"
>
> In contrast to
>
> guard let x = try? throwingFunction(y) catch {
> // you have to make your own print
> return
> }
>
> ---------------------
>
> However if you want to handle the error before you exit the scope it is quite
> inconvenient:
>
> guard let x = attempt({ _, _, error in /* handle error */ }, { try
> throwingFunction(y) } ) else {
> return
> }
>
> In contrast to:
>
> guard let x = try? throwingFunction(y) catch {
> // handle error
> return
> }
>
> - Maximilian
>
> Am 14.03.2016 um 18:00 schrieb Erica Sadun <[email protected]
> <mailto:[email protected]>>:
>
>>> On Mar 14, 2016, at 10:20 AM, Maximilian Hünenberger via swift-evolution
>>> <[email protected] <mailto:[email protected]>> wrote:
>>>
>>> How about only allowing "guard try? catch":
>>>
>>> guard let x = try? foo() catch { ... }
>>>
>>> This would address both concerns of Chris:
>>>
>>> • "This is inconsistent with what we currently have, because “if let” and
>>> “guard let” match against an optional and succeed iff the optional is
>>> present."
>>>
>>> • "This shouldn’t be tied to the presence of try, because it already means
>>> something (that the enclosed expression can throw). This:
>>> guard let x = try foo() …
>>> Already means “call foo, if it throws, propagate the error. If not, test
>>> the returned optional”."
>>>
>>>
>>> With "try?" it is clear that "foo()" doesn't throw an error in the guard
>>> expression and guard matches against an optional. This makes it unambiguous
>>> to "guard try else" which throws in this case.
>>>
>>> Kind regards
>>> - Maximilian
>>
>>
>>
>> I'm not a fan of the notion of guard/catch. However, it occurs to me that my
>> "attempt" code may address this issue.
>> I've recently updated it to take an arbitrary error handler, which if
>> omitted, simply prints the error. Otherwise it acts like try?
>> or if you set crashOnError, like try!. It works with guard.
>>
>> -- E
>>
>> github:
>> https://github.com/erica/SwiftUtility/blob/master/Sources/CoreError.swift
>> <https://github.com/erica/SwiftUtility/blob/master/Sources/CoreError.swift>
>>
>> public typealias CommonErrorHandlerType = (String, Int, ErrorType) -> Void
>>
>> /// Replacement for `try?` that introduces an error handler
>> /// The default handler prints an error before returning nil
>> ///
>> /// - Parameter file: source file, derived from `__FILE__` context literal
>> /// - Parameter line: source line, derived from `__LINE__` context literal
>> /// - Parameter crashOnError: defaults to false. When set to true
>> /// will raise a fatal error, emulating try! instead of try?
>> /// - Parameter errorHandler: processes the error, returns nil
>> ///
>> /// ```swift
>> /// attempt {
>> /// let mgr = NSFileManager.defaultManager()
>> /// try mgr.createDirectoryAtPath(
>> /// "/Users/notarealuser",
>> /// withIntermediateDirectories: true,
>> /// attributes: nil)
>> /// }
>> /// ```
>> ///
>> public func attempt<T>(
>> file fileName: String = __FILE__,
>> line lineNumber: Int = __LINE__,
>> crashOnError: Bool = false,
>> errorHandler: CommonErrorHandlerType = {
>> // Default handler prints context:error and returns nil
>> fileName, lineNumber, error in
>>
>> /// Retrieve last path component because #fileName is
>> /// not yet a thing in Swift
>> let trimmedFileName: String = (fileName as
>> NSString).lastPathComponent
>>
>> /// Force print and return nil like try?
>> print("Error \(trimmedFileName):\(lineNumber) \(error)")
>> },
>> closure: () throws -> T) -> T? {
>>
>> do {
>> // Return executes only if closure succeeds, returning T
>> return try closure()
>>
>> } catch {
>> // Emulate try! by crashing
>> if crashOnError {
>> print("Fatal error \(fileName):\(lineNumber): \(error)")
>> fatalError()
>> }
>>
>> // Execute error handler and return nil
>> errorHandler(fileName, lineNumber, error)
>> return nil
>> }
>> }
>>
>>
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution