Last active
December 19, 2015 14:34
-
-
Save erica/b203a13b0b71db430801 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Erica Sadun, http://ericasadun.com | |
Basic Errors | |
*/ | |
import Foundation | |
/// A basic utility error type that stores the reason for | |
/// a failed operation and the context under which the error | |
/// has occurred | |
public struct CoreError: ErrorType { | |
let (reason, context) : (String, String) | |
public init( | |
_ reason: String, | |
_ context: String = __FILE__) | |
{ | |
(self.reason, self.context) = (reason, context) | |
} | |
} | |
/// By adopting Contextualizable, constructs can build errors | |
/// specific to their calling conditions | |
public protocol Contextualizable {} | |
/// Adding default implementation for error building | |
public extension Contextualizable { | |
/// Creates a context error at the point of failure, picking | |
/// up the file, function, and line of the error event | |
public func BuildContextError( | |
items: Any..., | |
file: String = (__FILE__ as NSString).lastPathComponent, | |
function: String = __FUNCTION__, | |
line: Int = __LINE__ | |
) -> CoreError | |
{ | |
let reasons = items.map({"\($0)"}).joinWithSeparator(", ") | |
let context = "\(function):\(self.dynamicType):\(file):\(line) " | |
return CoreError(reasons, context) | |
} | |
} | |
/// A lighter weight alternative to Contextualizable that still | |
/// picks up file and line context for error handling | |
/// | |
/// - param items: Caller can supply zero or more instances as "reasons", which | |
/// need not be strings. Their default representation will be added | |
/// to the 'reasons' list. | |
public func ContextError( | |
items: Any..., | |
file: String = (__FILE__ as NSString).lastPathComponent, | |
line: Int = __LINE__ | |
) -> CoreError | |
{ | |
let reasons = items.map({"\($0)"}).joinWithSeparator(", ") | |
let context = "\(file):\(line) " | |
return CoreError(reasons, context) | |
} | |
/// Replacement for `try?` that introduces printing for | |
/// error conditions instead of discarding those errors | |
/// | |
/// - Parameter shouldCrash: defaults to false. When set to true | |
/// will raise a fatal error, emulating try! instead of try? | |
/// | |
/// ```swift | |
/// attempt { | |
/// let mgr = NSFileManager.defaultManager() | |
/// try mgr.createDirectoryAtPath( | |
/// "/Users/notarealuser", | |
/// withIntermediateDirectories: true, | |
/// attributes: nil) | |
/// } | |
/// | |
public func attempt<T>( | |
line line: Int = __LINE__, | |
shouldCrash: Bool = false, | |
closure: () throws -> T | |
) -> T? | |
{ | |
do { | |
/// Return executes only if closure succeeds | |
return try closure() | |
} catch { | |
/// Emulate try! by crashing | |
if shouldCrash { | |
print("Fatal error on line \(line): \(error)") | |
abort() | |
} | |
/// Force print and return nil like try? | |
print("Error \(line): \(error)") | |
return nil | |
} | |
} | |
/// Alternative to attempt that ignores any results and returns | |
/// a Boolean value indicating success | |
public func testAttempt<T>( | |
line line: Int = __LINE__, | |
shouldCrash: Bool = false, | |
closure: () throws -> T | |
) -> Bool | |
{ | |
/// Throw away result but check for non-nil. Thanks nuclearace | |
return attempt( | |
line: line, | |
shouldCrash: shouldCrash, | |
closure: closure) == nil ? false : true | |
} |
On Linux we need 'import Glibc' for 'abort()'.
Some off the top of my head:
Greatest readability and clarity of intent
Why are reason
and context
not named in the init?
Why let (reason, context) : (String, String)
instead of over two lines?
Why is reason a String
and not an enum case
?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
<My goals are:
Greatest readability and clarity of intent
Easiest modification
Space for commenting where needed>
You have achieved your goals!