[swift-evolution] Idea: Extend "guard" to try-statements, with a catch block

Erica Sadun erica at ericasadun.com
Mon Mar 14 12:00:26 CDT 2016


> On Mar 14, 2016, at 10:20 AM, Maximilian Hünenberger via swift-evolution <swift-evolution at swift.org> 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

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
        }
}


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160314/b277cde7/attachment.html>


More information about the swift-evolution mailing list