/* (Requires Swift 1.2) In the version above you'll notice that there's use of forced Optional unwrapping. This is potentially hazardous. Here's a version that deals with Optional values safely. Having to 'reduce' Optional Strings adds significant complexity. Below, I've shown 2 ways of dealing with this (Monadic bind & 'if let' syntax). */ import Foundation // Monadic bind for Optionals infix operator >>= {associativity left} func >>= (m: A?, f: A -> B?) -> B? { if let x = m {return f(x)} return .None } extension Character { func utf8() -> UInt8 { let utf8 = String(self).utf8 return utf8[utf8.startIndex] } } func encrypt(key:Character, c:Character) -> String? { let byte = [key.utf8() ^ c.utf8()] return String(bytes: byte, encoding: NSUTF8StringEncoding) } // Curried func for convenient use with map func encryptKey(key:String)(message:String) -> String? { return reduce(zip(key, message), Optional("")) { str, c in str >>= { s in encrypt(c).map {s + $0} }} } let message = "Hello world!" let secretKey = "(:.,?P!9@PAz" // really should be randomly generated! let encryptedMessage = encryptKey(secretKey)(message: message) // > .Some("`_B@PpVV2<%[") // As the encryptKey func is curried it can be passed directly to map let decryptedMessage = encryptedMessage.map(encryptKey(secretKey)) // > .Some("Hello world!") /* here's how the encrypt function would look like using 'if let' syntax func encryptKey_if_let(key:String)(message:String) -> String? { return reduce(zip(key, message), Optional("")) { if let str = $0, c = encrypt($1) { return str + c } else { return .None} } } */