> On 16 Aug 2016, at 20:24, Justin Jia via swift-evolution > <swift-evolution@swift.org> wrote: > > Thank you for the sharing how you solve this problem! It seems like the best > workaround so far. > > I wish $0 can be replaced by the actual name. (Maybe tuples?) > > let a = (x: x, y: y) > let result = a.my_map { foo(x: $0.x, y: $0.y } > > In my_map unwrap all variables inside tuple? > > I agree that short-circuiting is an issue. But personally I still think the > imperfect solution is good enough. But I'll try to find other possible > solutions.
One technique around this is to introduce a set of generic library functions that try to unwrap all of their arguments and construct a tuple thereof if every argument evaluated to `.some(_)`. The evaluation of expressions can also be delayed with @autoclosure: func unwrap<A, B>(_ a: A?, _ b: @autoclosure () throws -> B?) rethrows -> (A, B)? { guard let a = a, let b = try b() else { return nil } return (a, b) } func unwrap<A, B, C>(_ a: A?, _ b: @autoclosure () throws -> B?, _ c: @autoclosure () throws -> C?) rethrows -> (A, B, C)? { guard let a = a, let b = try b(), let c = try c() else { return nil } return (a, b, c) } // ...etc, for higher arities than 3. Repetitive library code? Yes. But can be easily generated with a code generator such as swift.gyb, and you hardly need it for arities higher than a few. You can use `unwrap()` together with `if let` or `guard let`: if let (a, b, c) = unwrap(Int("1"), Double("12"), Bool("true")) { print(a, b, c) //=> 1 12.0 true } Or even `.map()` if you like. This use is similar to Dave Sweeris' suggestion of `optionally()`: struct User { var username, language: String } let data = ["u": "chris", "l": "swift"] let user = unwrap(data["u"], data["l"]).map {u, l in User(username: u, language: l) } print(user) //=> Optional(User(username: "chris", language: "swift")) I guess that reads better than this equivalent with `.flatMap()` and `.map()`: let user = data["u"].flatMap { u in data["l"].map { l in User(username: u, language: l) } } OTOH, it isn't much better than either delayed `let` initialisation: let user: User? if let u = data["u"], let l = data["l"] { user = User(username: u, language: l) } else { user = nil } Or the use of a one-off closure like so: let user: User? = { guard let u = data["u"], let l = data["l"] else { return nil } return User(username: u, language: l) }() — Pyry (Sorry for the sparing use of newlines in the examples above. Tried to keep it tight.)
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution