Last active
August 29, 2015 14:16
-
-
Save pyrtsa/29f41936a6b3f145e0c0 to your computer and use it in GitHub Desktop.
Foolish syntactic idea for Swift: "let else"
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
/// The improved `if let` syntax in Swift 1.2 is all cool. But there's | |
/// one pattern it doesn't solve great: writing a block of error | |
/// handling right where `nil` is returned: | |
func validate1(json: AnyObject) -> String { | |
var error: String? | |
if let name = json["name"] as? String ?? { error = "missing name"; return nil }, | |
let year = json["year"] as? Int ?? { error = "missing year"; return nil } | |
{ | |
// ... | |
return "no errors" | |
} else { | |
return error! | |
} | |
} | |
/// Sometimes, I'd still like to return from the whole function early, | |
/// and then handle the successful case without any nesting at all. | |
/// That can be done by (ab)using `ImplicitlyUnwrappedOptional` with | |
/// both Swift 1.1 and Swift 1.2 as follows: | |
func validate2(json: AnyObject) -> String { | |
let name: String! = json["name"] as? String | |
if name == nil { | |
return "missing name" | |
} | |
let year: Int! = json["year"] as? Int | |
if year == nil { | |
return "missing year" | |
} | |
// ... | |
return "no errors" | |
} | |
/// But there would be even less noise if the following was made possible: | |
func validate3(json: AnyObject) -> String { | |
let name = json["name"] as? String else { | |
return "missing name" | |
} | |
let year = json["year"] as? Int else { | |
return "missing year" | |
} | |
// ... | |
return "no errors" | |
} | |
/// Inventing new syntax often goes circles around the real problem. | |
/// What I really wished was if Swift had Haskell's `do` notation, | |
/// but that's a whole other story. And we've already got the | |
/// `if let`, which I find this to be a logical extension to. | |
/// -- @pyrtsa |
This got implemented in Swift 2.0 as the guard let
statement, yay!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Before anyone else says it out aloud, one problematic point here is, a block like this must
return
with the return type of the function it's part of. That's probably breaking the law of the least astonishment, but makes sense when you think about it.That would also mean,
let else
can't be used at file scope, because what would it then return? But I don't see that as a problem.The REPL could be made to support this, though, by enforcing the block to have implicit return type of
Void
.Alternative to the missing feature of exceptions
I think this pattern could work very well to fulfil the request of adding exceptions to Swift. That is, actually better than exceptions, since there'd be no surprises to callers of such functions (because the error reporting would still happen through the function return type).